#!/usr/bin/env node --max-old-space-size=8192
/**
 * OpenHarmony 全量代码知识库生成器
 * 
 * 功能：
 * 1. 扫描 /home/yaoruozi/openharmony/code1028 下的所有代码
 * 2. 提取 .h/.cpp 中的类、成员函数、静态函数、内联函数、宏
 * 3. 提取文件与 BUILD.gn 的关联关系
 * 4. 提取 test/tests 目录下的测试模式和 GN 配置
 * 5. 提取 Mock 使用模式（包括自定义场景）
 * 6. 提取 NAPI 和 NDK 使用模式
 * 7. 生成结构化的知识库 JSON 文件
 */

const fs = require('fs');
const path = require('path');

// 配置
const OH_ROOT = process.env.OH_ROOT || '/home/yaoruozi/openharmony/code1028';
const OUTPUT_DIR = path.join(__dirname, '../core/knowledge');
const MAX_FILE_SIZE = 500 * 1024; // 500KB，超过的文件只分析结构
const MAX_FILES_TO_SCAN = 3200000; // 最多扫描文件数（320万，支持全量扫描）
const MAX_SCAN_DEPTH = 22; // 最大扫描深度（用于查找test/tests目录）
const BATCH_SAVE_INTERVAL = 1000; // 每处理1000个文件保存一次到临时文件（避免内存过大）

// 需要跳过的文件列表（避免卡死）
const SKIP_FILES = [
    'base/notification/distributed_notification_service/services/ans/src/permission_filter.cpp',
    'foundation/arkui/ace_engine/test/unittest/core/pattern/overlay/overlay_manager_popup_test_ng.cpp',
    'foundation/arkui/ace_engine/test/unittest/core/base/view_abstract_model_test_ng.cpp',
    'foundation/arkui/ace_engine/test/unittest/core/event/focus_hub_test_ng_branch_coverage.cpp',
    'foundation/arkui/ace_engine/test/unittest/core/pattern/grid/grid_pattern_test_ng.cpp'
];

// 需要跳过的目录（避免整个目录卡死）
const SKIP_DIRS = [
    // 可以添加整个目录路径，例如：
    // 'foundation/arkui/ace_engine/test/unittest/core/pattern'
];

// 断点续传：已处理的文件列表
const PROCESSED_FILES_SET = new Set();
const PROCESSED_FILES_FILE = path.join(__dirname, '../.processed-files.json');

// 统计信息
const stats = {
    totalFiles: 0,
    headerFiles: 0,
    sourceFiles: 0,
    testFiles: 0,
    buildGnFiles: 0,
    classes: 0,
    functions: 0,
    mocks: 0,
    napiFunctions: 0,
    ndkFunctions: 0,
    lastProcessedFile: '',
    lastProcessedDirectory: ''
};

// 知识库数据结构
const knowledgeBase = {
    metadata: {
        version: '2.1.0',
        generatedAt: new Date().toISOString(),
        ohRoot: OH_ROOT,
        stats: {}
    },
    classes: [],                    // 类定义信息（包含成员变量）
    functions: [],                  // 函数定义信息
    headerDependencies: [],         // 头文件依赖关系
    buildGnRelations: [],           // 文件与 BUILD.gn 的关联
    buildGnExternalDeps: [],        // BUILD.gn 的 external_deps 映射
    testPatterns: [],               // 测试模式
    testFileDependencies: [],       // 测试文件依赖关系
    mockPatterns: [],               // Mock 使用模式
    functionCoveragePatterns: [],  // 函数覆盖模式（成员函数、静态函数等）
    functionCallRelations: [],     // 函数调用关系（同文件、同模块）
    testFunctionStrategies: [],    // 测试函数策略（不同函数类型的测试方式）
    branchCoveragePatterns: [],    // 分支覆盖模式（if/switch/循环/异常）
    bestPractices: [],              // 最佳实践总结
    coverageQualityMetrics: [],    // 覆盖质量指标
    napiPatterns: [],               // NAPI 使用模式
    ndkPatterns: []                 // NDK 使用模式
};

/**
 * 保存批次数据到临时文件（每1000个文件保存一次）
 * @param {number} batchNumber - 批次号
 * @returns {boolean} 是否保存成功
 */
function saveBatchToTempFile(batchNumber) {
    try {
        const tempDir = path.join(OUTPUT_DIR, 'temp_batches');
        if (!fs.existsSync(tempDir)) {
            fs.mkdirSync(tempDir, { recursive: true });
        }
        
        const batchData = {
            batchNumber,
            fileCount: stats.totalFiles,
            timestamp: new Date().toISOString(),
            classes: [...knowledgeBase.classes],
            functions: [...knowledgeBase.functions],
            headerDependencies: [...knowledgeBase.headerDependencies],
            buildGnRelations: [...knowledgeBase.buildGnRelations],
            buildGnExternalDeps: [...knowledgeBase.buildGnExternalDeps],
            testPatterns: [...knowledgeBase.testPatterns],
            testFileDependencies: [...knowledgeBase.testFileDependencies],
            mockPatterns: [...knowledgeBase.mockPatterns],
            functionCoveragePatterns: [...knowledgeBase.functionCoveragePatterns],
            functionCallRelations: [...knowledgeBase.functionCallRelations],
            testFunctionStrategies: [...knowledgeBase.testFunctionStrategies],
            branchCoveragePatterns: [...knowledgeBase.branchCoveragePatterns],
            coverageQualityMetrics: [...knowledgeBase.coverageQualityMetrics],
            napiPatterns: [...knowledgeBase.napiPatterns],
            ndkPatterns: [...knowledgeBase.ndkPatterns]
        };
        
        const batchFile = path.join(tempDir, `batch-${batchNumber}.json`);
        fs.writeFileSync(batchFile, JSON.stringify(batchData, null, 2), 'utf-8');
        
        // 清空数组，释放内存（只保留统计信息）
        knowledgeBase.classes = [];
        knowledgeBase.functions = [];
        knowledgeBase.headerDependencies = [];
        knowledgeBase.buildGnRelations = [];
        knowledgeBase.buildGnExternalDeps = [];
        knowledgeBase.testPatterns = [];
        knowledgeBase.testFileDependencies = [];
        knowledgeBase.mockPatterns = [];
        knowledgeBase.functionCoveragePatterns = [];
        knowledgeBase.functionCallRelations = [];
        knowledgeBase.testFunctionStrategies = [];
        knowledgeBase.branchCoveragePatterns = [];
        knowledgeBase.coverageQualityMetrics = [];
        knowledgeBase.napiPatterns = [];
        knowledgeBase.ndkPatterns = [];
        
        return true;
    } catch (error) {
        console.warn(`[BATCH] 保存批次失败: ${error.message}`);
        return false;
    }
}

/**
 * 递归扫描目录（支持深度遍历查找test/tests目录）
 * @param {string} dir - 要扫描的目录
 * @param {Function} callback - 文件处理回调，返回true表示停止扫描
 * @param {number} maxDepth - 最大扫描深度
 * @param {number} currentDepth - 当前深度
 * @param {Object} stopFlag - 停止标志对象 {shouldStop: boolean}
 */
function scanDirectory(dir, callback, maxDepth = MAX_SCAN_DEPTH, currentDepth = 0, stopFlag = null) {
    // 如果设置了停止标志且已停止，直接返回
    if (stopFlag && stopFlag.shouldStop) {
        return;
    }
    
    if (currentDepth > maxDepth || !fs.existsSync(dir)) {
        return;
    }

    try {
        const entries = fs.readdirSync(dir, { withFileTypes: true });
        
        for (const entry of entries) {
            // 检查停止标志
            if (stopFlag && stopFlag.shouldStop) {
                return;
            }
            
            const fullPath = path.join(dir, entry.name);
            
            // 跳过不需要的目录
            if (entry.isDirectory()) {
                // 跳过常见的排除目录（包括用户指定的目录）
                const excludedDirs = [
                    '.git', 'node_modules', 'out', '.vscode', '.idea', 'prebuilts', 'third_party',
                    '.repo', 'applications', 'docs', 'interface', 'ide'
                ];
                
                // 如果目录在排除列表中，跳过
                if (excludedDirs.includes(entry.name)) {
                    continue;
                }
                
                // ⭐ 重要：test/tests 目录及其所有子目录都需要深入扫描（22层深度）
                // 包括：unittest、fuzztest、moduletest、mock、aottest、scenarios 等所有子目录，一个也不放过
                // 目标：扫描每个工程的每个文件，全部学习到
                if (entry.name === 'test' || entry.name === 'tests') {
                    // test/tests 目录下的所有内容都要扫描（包括 unittest、fuzztest、moduletest、mock、aottest 等）
                    // 递归深度：22层，确保覆盖所有嵌套的测试文件和目录
                    scanDirectory(fullPath, callback, maxDepth, currentDepth + 1, stopFlag);
                } else if (currentDepth < maxDepth) {
                    // 其他所有目录正常递归（最多22层），确保扫描到所有文件
                    // 包括：unittest、fuzztest、moduletest、mock 等如果作为独立目录存在也会被扫描
                    scanDirectory(fullPath, callback, maxDepth, currentDepth + 1, stopFlag);
                }
            } else if (entry.isFile()) {
                // 只处理 C++ 相关文件
                const ext = path.extname(entry.name).toLowerCase();
                const cppExtensions = ['.cpp', '.h', '.hpp', '.c', '.cc', '.cxx', '.hxx'];
                const isBuildGn = entry.name === 'BUILD.gn';
                
                if (cppExtensions.includes(ext) || isBuildGn) {
                    const result = callback(fullPath);
                    // 如果callback返回true或stopFlag已设置，停止扫描
                    if (result === true || (stopFlag && stopFlag.shouldStop)) {
                        if (stopFlag) {
                            stopFlag.shouldStop = true;
                        }
                        return;
                    }
                }
                // 其他文件（.ts, .txt, .json, .md 等）直接跳过，不计数
            }
        }
    } catch (error) {
        // 忽略权限错误等
        if (currentDepth === 0 || error.code !== 'EACCES') {
            console.warn(`[WARN] 无法扫描目录 ${dir}: ${error.message}`);
        }
    }
}

/**
 * 提取类定义信息（包含详细的成员变量信息）
 */
function extractClassInfo(content, filePath, timeoutChecker = null) {
    const classes = [];
    
    // 匹配类定义（支持模板类）
    const classRegex = /(?:template\s*<[^>]+>\s*)?class\s+(\w+)(?:\s*:\s*(?:public|private|protected)\s+[\w\s,<>:]+)?\s*\{/g;
    let match;
    
    let classMatchCount = 0;
    const MAX_CLASS_MATCHES = 1000; // 限制类匹配数量，避免无限循环
    const EXTRACT_TIMEOUT = 5000; // 5秒超时
    const extractStartTime = Date.now();
    
    while ((match = classRegex.exec(content)) !== null && classMatchCount < MAX_CLASS_MATCHES) {
        // 检查超时（每10次匹配检查一次，避免性能损失）
        if (classMatchCount % 10 === 0) {
            if (timeoutChecker && timeoutChecker()) {
                console.warn(`[TIMEOUT] extractClassInfo 超时: ${path.relative(process.env.OH_ROOT || '', filePath)}`);
                break;
            }
            if (Date.now() - extractStartTime > EXTRACT_TIMEOUT) {
                console.warn(`[TIMEOUT] extractClassInfo 内部超时 (5s): ${path.relative(process.env.OH_ROOT || '', filePath)}`);
                break;
            }
        }
        
        classMatchCount++;
        const className = match[1];
        const classStart = match.index;
        
        // 查找类结束位置（简化处理）
        let braceCount = 0;
        let inClass = false;
        let classEnd = classStart;
        
        for (let i = classStart; i < content.length && i < classStart + 10000; i++) {
            if (content[i] === '{') {
                braceCount++;
                inClass = true;
            } else if (content[i] === '}') {
                braceCount--;
                if (inClass && braceCount === 0) {
                    classEnd = i;
                    break;
                }
            }
        }
        
        const classBody = content.substring(classStart, classEnd + 1);
        
        // 提取成员函数（增强版）
        const memberFunctions = extractMemberFunctions(classBody, className, filePath);
        
        // 提取成员变量（包含详细信息）
        const memberVariables = extractMemberVariables(classBody);
        
        // 提取宏定义
        const macros = extractMacros(classBody);
        
        classes.push({
            name: className,
            filePath: path.relative(OH_ROOT, filePath),
            isAbstract: /=\s*0\s*;/.test(classBody),
            isTemplate: /template\s*</.test(match[0]),
            memberFunctions: memberFunctions,  // 包含完整信息
            memberVariables: memberVariables,  // 保存详细信息
            macros: macros,
            accessSpecifiers: {
                public: (classBody.match(/public:/g) || []).length,
                private: (classBody.match(/private:/g) || []).length,
                protected: (classBody.match(/protected:/g) || []).length
            },
            // 函数调用方式分析
            functionCallPatterns: analyzeFunctionCallPatterns(classBody, memberFunctions)
        });
    }
    
    return classes;
}

/**
 * 提取成员函数（增强版：包含调用方式信息）
 */
function extractMemberFunctions(classBody, className, filePath) {
    const functions = [];
    
    // 匹配成员函数声明/定义
    const funcPatterns = [
        // 普通成员函数
        /(?:virtual\s+)?(?:static\s+)?(?:inline\s+)?(\w+(?:<[\w\s,:<>*&]+>)?(?:\s*\*|\s*&)?)\s+(\w+)\s*\(([^)]*)\)(?:\s+const)?(?:\s+override)?(?:\s*=\s*0)?(?:\s*[{;])/g,
        // 构造函数/析构函数
        /(?:explicit\s+)?(\w+)::?(\w+)\s*\(([^)]*)\)(?:\s*:\s*[^)]+)?\s*[{;]/g
    ];
    
    for (const pattern of funcPatterns) {
        let match;
        let memberFuncMatchCount = 0;
        const MAX_MEMBER_FUNC_MATCHES = 500; // 限制成员函数匹配数量
        while ((match = pattern.exec(classBody)) !== null && memberFuncMatchCount < MAX_MEMBER_FUNC_MATCHES) {
            memberFuncMatchCount++;
            const funcName = match[2] || match[1];
            
            // 跳过构造函数和析构函数
            if (funcName === className || funcName === `~${className}`) {
                continue;
            }
            
            const isStatic = /static\s+/.test(match[0]);
            const isVirtual = /virtual\s+/.test(match[0]);
            const isInline = /inline\s+/.test(match[0]);
            const isConst = /const\s*[;{]/.test(match[0]);
            const isPureVirtual = /=\s*0\s*;/.test(match[0]);
            
            functions.push({
                name: funcName,
                isStatic,
                isVirtual,
                isInline,
                isConst,
                isPureVirtual,
                returnType: match[1] ? match[1].trim() : 'void',
                params: match[3] ? match[3].trim() : '',
                signature: match[0].trim(),
                filePath: path.relative(OH_ROOT, filePath)
            });
        }
    }
    
    return functions;
}

/**
 * 提取成员变量（包括指针类型、引用类型、智能指针等）
 */
function extractMemberVariables(classBody) {
    const variables = [];
    
    // 匹配各种类型的成员变量
    const varPatterns = [
        // 1. 以下划线结尾的成员变量（OpenHarmony 命名约定）
        /(\w+(?:<[\w\s,:<>*&]+>)?(?:\s*\*|\s*&)?)\s+(\w+_)\s*[;=]/g,
        // 2. 智能指针类型
        /(std::(?:shared_ptr|unique_ptr|weak_ptr)<[\w\s,:<>*&]+>)\s+(\w+_?)\s*[;=]/g,
        // 3. 原始指针
        /(\w+(?:<[\w\s,:<>*&]+>)?\s*\*+)\s+(\w+_?)\s*[;=]/g,
        // 4. 引用类型
        /(\w+(?:<[\w\s,:<>*&]+>)?\s*&)\s+(\w+_?)\s*[;=]/g,
        // 5. 普通类型（包含数组、函数指针等）
        /(\w+(?:<[\w\s,:<>*&]+>)?(?:\s*\[\d*\])?)\s+(\w+_?)\s*[;=]/g,
        // 6. 枚举类型
        /(enum\s+\w+)\s+(\w+_?)\s*[;=]/g
    ];
    
    for (const pattern of varPatterns) {
        let match;
        let varMatchCount = 0;
        const MAX_VAR_MATCHES = 500; // 限制成员变量匹配数量
        while ((match = pattern.exec(classBody)) !== null && varMatchCount < MAX_VAR_MATCHES) {
            varMatchCount++;
            const varType = match[1].trim();
            const varName = match[2];
            
            // 判断变量类型特征
            const isPointer = /\*/.test(varType);
            const isReference = /&/.test(varType) && !/\*/.test(varType);
            const isSmartPointer = /(shared_ptr|unique_ptr|weak_ptr)/.test(varType);
            const isArray = /\[\d*\]/.test(varType);
            const isTemplate = /<[^>]+>/.test(varType);
            
            variables.push({
                name: varName,
                type: varType,
                isPointer,
                isReference,
                isSmartPointer,
                isArray,
                isTemplate,
                pointerLevel: (varType.match(/\*/g) || []).length
            });
        }
    }
    
    // 去重（基于变量名）
    const seen = new Set();
    return variables.filter(v => {
        if (seen.has(v.name)) {
            return false;
        }
        seen.add(v.name);
        return true;
    });
}

/**
 * 提取宏定义
 */
function extractMacros(content) {
    const macros = [];
    
    // 匹配 #define 宏
    const macroPattern = /#define\s+(\w+)(?:\([^)]*\))?\s+(.+)/g;
    let match;
    
    while ((match = macroPattern.exec(content)) !== null) {
        macros.push({
            name: match[1],
            definition: match[2].trim()
        });
    }
    
    return macros;
}

/**
 * 提取全局函数（增强版：包含调用关系）
 */
function extractGlobalFunctions(content, filePath, timeoutChecker = null) {
    const functions = [];
    const relativePath = path.relative(OH_ROOT, filePath);
    
    // 匹配全局函数定义（不在类内部）
    const globalFuncPattern = /(?:^|\n)(?:extern\s+(?:"C"\s+)?)?(?:static\s+)?(?:inline\s+)?(\w+(?:<[\w\s,:<>*&]+>)?(?:\s*\*|\s*&)?)\s+(\w+)\s*\(([^)]*)\)\s*\{/g;
    let match;
    
    let funcMatchCount = 0;
    const MAX_FUNC_MATCHES = 2000; // 限制函数匹配数量，避免无限循环
    const EXTRACT_TIMEOUT = 5000; // 5秒超时
    const extractStartTime = Date.now();
    
    while ((match = globalFuncPattern.exec(content)) !== null && funcMatchCount < MAX_FUNC_MATCHES) {
        // 检查超时（每10次匹配检查一次，避免性能损失）
        if (funcMatchCount % 10 === 0) {
            if (timeoutChecker && timeoutChecker()) {
                console.warn(`[TIMEOUT] extractGlobalFunctions 超时: ${path.relative(process.env.OH_ROOT || '', filePath)}`);
                break;
            }
            if (Date.now() - extractStartTime > EXTRACT_TIMEOUT) {
                console.warn(`[TIMEOUT] extractGlobalFunctions 内部超时 (5s): ${path.relative(process.env.OH_ROOT || '', filePath)}`);
                break;
            }
        }
        
        funcMatchCount++;
        const funcName = match[2];
        const isStatic = /static\s+/.test(match[0]);
        const isInline = /inline\s+/.test(match[0]);
        const isExternC = /extern\s+"C"/.test(match[0]);
        
        // 提取函数体中的调用关系
        const funcStart = match.index + match[0].length;
        const funcBody = extractFunctionBody(content, funcStart);
        
        functions.push({
            name: funcName,
            isStatic,
            isInline,
            isExternC,
            returnType: match[1].trim(),
            params: match[3].trim(),
            signature: match[0].trim(),
            filePath: relativePath,
            calledFunctions: extractCalledFunctions(funcBody, relativePath),
            hasPointerUsage: /->|\./.test(funcBody)
        });
    }
    
    return functions;
}

/**
 * 提取函数体内容
 */
function extractFunctionBody(content, startIndex) {
    let braceCount = 0;
    let inFunction = false;
    let endIndex = startIndex;
    
    for (let i = startIndex; i < content.length && i < startIndex + 10000; i++) {
        if (content[i] === '{') {
            braceCount++;
            inFunction = true;
        } else if (content[i] === '}') {
            braceCount--;
            if (inFunction && braceCount === 0) {
                endIndex = i;
                break;
            }
        }
    }
    
    return content.substring(startIndex, endIndex + 1);
}

/**
 * 提取函数调用关系（同文件、同模块）
 */
function extractCalledFunctions(funcBody, filePath) {
    const calledFunctions = [];
    
    // 匹配函数调用（包括成员函数调用）
    const callPatterns = [
        // 直接调用：functionName(...)
        /(\w+)\s*\(/g,
        // 成员函数调用：obj->method(...) 或 obj.method(...)
        /(?:->|\.)\s*(\w+)\s*\(/g,
        // 静态函数调用：ClassName::method(...)
        /(\w+)\s*::\s*(\w+)\s*\(/g
    ];
    
    for (const pattern of callPatterns) {
        let match;
        while ((match = pattern.exec(funcBody)) !== null) {
            const funcName = match[2] || match[1];
            
            // 跳过常见的关键字和操作符
            if (['if', 'for', 'while', 'switch', 'return', 'new', 'delete', 'sizeof', 'typeid', 'static_cast', 'dynamic_cast', 'reinterpret_cast', 'const_cast'].includes(funcName)) {
                continue;
            }
            
            calledFunctions.push({
                name: funcName,
                callType: match[2] ? 'static_member' : (match[0].includes('->') ? 'pointer_member' : (match[0].includes('.') ? 'object_member' : 'direct')),
                className: match[2] ? match[1] : null
            });
        }
    }
    
    // 去重
    const seen = new Set();
    return calledFunctions.filter(f => {
        const key = `${f.name}_${f.callType}`;
        if (seen.has(key)) {
            return false;
        }
        seen.add(key);
        return true;
    });
}

/**
 * 分析类中函数的调用模式
 */
function analyzeFunctionCallPatterns(classBody, memberFunctions) {
    const patterns = {
        pointerCalls: [],
        staticCalls: [],
        memberCalls: [],
        externalCalls: []
    };
    
    // 分析成员函数中的调用方式
    for (const func of memberFunctions) {
        if (func.isStatic) {
            patterns.staticCalls.push(func.name);
        } else {
            // 查找函数体中的调用
            const funcPattern = new RegExp(`(?:\\w+\\s+)?${func.name}\\s*\\([^)]*\\)\\s*\\{([^{}]*(?:\\{[^{}]*\\}[^{}]*)*)\\}`);
            const funcMatch = classBody.match(funcPattern);
            if (funcMatch) {
                const funcBody = funcMatch[1];
                
                // 检查指针调用
                if (/->/.test(funcBody)) {
                    patterns.pointerCalls.push(func.name);
                }
                
                // 检查成员调用
                if (/\.\w+\(/.test(funcBody)) {
                    patterns.memberCalls.push(func.name);
                }
            }
        }
    }
    
    return patterns;
}

/**
 * 提取 NAPI 函数
 */
function extractNAPI(content, filePath) {
    const napiFunctions = [];
    
    // 匹配 NAPI 函数定义
    const napiPatterns = [
        /napi_value\s+(\w+)\s*\([^)]*napi_env[^)]*\)/g,
        /static\s+napi_value\s+(\w+)\s*\([^)]*napi_env[^)]*\)/g,
        /Napi::\w+\s+(\w+)\s*\([^)]*Napi::Env[^)]*\)/g
    ];
    
    for (const pattern of napiPatterns) {
        let match;
        let napiMatchCount = 0;
        const MAX_NAPI_MATCHES = 500; // 限制NAPI匹配数量
        while ((match = pattern.exec(content)) !== null && napiMatchCount < MAX_NAPI_MATCHES) {
            napiMatchCount++;
            napiFunctions.push({
                name: match[1],
                type: 'NAPI',
                filePath: path.relative(OH_ROOT, filePath)
            });
        }
    }
    
    return napiFunctions;
}

/**
 * 提取 NDK 函数
 */
function extractNDK(content, filePath) {
    const ndkFunctions = [];
    
    // 匹配 OH_ 开头的 NDK 函数
    const ndkPattern = /(?:^|\n)(?:extern\s+(?:"C"\s+)?)?(\w+(?:\s*\*)?)\s+(OH_\w+)\s*\(([^)]*)\)/g;
    let match;
    
    let ndkMatchCount = 0;
    const MAX_NDK_MATCHES = 500; // 限制NDK匹配数量
    while ((match = ndkPattern.exec(content)) !== null && ndkMatchCount < MAX_NDK_MATCHES) {
        ndkMatchCount++;
        ndkFunctions.push({
            name: match[2],
            returnType: match[1].trim(),
            type: 'NDK',
            filePath: path.relative(OH_ROOT, filePath)
        });
    }
    
    return ndkFunctions;
}

/**
 * 提取 Mock 模式（增强版：关注使用时机和场景）
 */
function extractMockPatterns(content, filePath) {
    const mockPatterns = [];
    const relativePath = path.relative(OH_ROOT, filePath);
    
    // 检查是否是 Mock 文件
    const isMockFile = /mock_|_mock/i.test(path.basename(filePath));
    
    if (isMockFile || content.includes('MOCK_METHOD') || content.includes('MOCK_CONST_METHOD')) {
        // 提取 Mock 类定义
        const mockClassPattern = /class\s+(Mock\w+|\w+Mock)\s*:\s*public\s+(\w+)/g;
        let match;
        
        while ((match = mockClassPattern.exec(content)) !== null) {
            // 提取 MOCK_METHOD
            const mockMethods = [];
            const methodPattern = /MOCK_(?:CONST_)?METHOD\d+\s*\(([^,]+),\s*(\w+)\s*,\s*\(([^)]*)\)/g;
            let methodMatch;
            
            while ((methodMatch = methodPattern.exec(content)) !== null) {
                mockMethods.push({
                    returnType: methodMatch[1].trim(),
                    name: methodMatch[2],
                    params: methodMatch[3]
                });
            }
            
            mockPatterns.push({
                type: 'mock_definition',
                mockClassName: match[1],
                baseClassName: match[2],
                filePath: relativePath,
                methods: mockMethods,
                headerIncludes: extractHeaderDependencies(content, filePath).map(d => d.header)
            });
        }
    }
    
    // 提取测试类中的 Mock 使用模式
    if (content.includes('EXPECT_CALL') || content.includes('ON_CALL') || content.includes('MOCK_METHOD')) {
        const usagePatterns = extractMockUsageInTests(content, filePath);
        if (usagePatterns.length > 0) {
            mockPatterns.push(...usagePatterns);
        }
    }
    
    return mockPatterns;
}

/**
 * 提取测试函数中的 Mock 使用（关注使用时机和场景）
 */
function extractMockUsageInTests(content, filePath) {
    const patterns = [];
    const relativePath = path.relative(OH_ROOT, filePath);
    
    // 提取测试类定义
    const testClassPattern = /class\s+(\w+Test\w*)\s*:\s*public\s+testing::Test/g;
    const testClasses = [];
    let match;
    
    while ((match = testClassPattern.exec(content)) !== null) {
        testClasses.push({
            name: match[1],
            startIndex: match.index
        });
    }
    
    // 如果没有显式的测试类，查找 HWTEST_F 或 TEST_F
    if (testClasses.length === 0) {
        const testFPattern = /(?:HWTEST_F|TEST_F)\s*\(\s*(\w+)\s*,/g;
        while ((match = testFPattern.exec(content)) !== null) {
            testClasses.push({
                name: match[1],
                startIndex: match.index
            });
        }
    }
    
    // 为每个测试类提取 Mock 使用
    for (const testClass of testClasses) {
        // 查找类的结束位置（简化处理）
        let classEnd = content.length;
        const classStart = testClass.startIndex;
        let braceCount = 0;
        let inClass = false;
        
        for (let i = classStart; i < content.length && i < classStart + 50000; i++) {
            if (content[i] === '{') {
                braceCount++;
                inClass = true;
            } else if (content[i] === '}') {
                braceCount--;
                if (inClass && braceCount === 0) {
                    classEnd = i;
                    break;
                }
            }
        }
        
        const classBody = content.substring(classStart, classEnd + 1);
        
        // 提取 SetUp 和 TearDown
        const setUpMatch = classBody.match(/void\s+SetUp\(\)\s*(?:override\s*)?\{([^{}]*(?:\{[^{}]*\}[^{}]*)*)\}/);
        const tearDownMatch = classBody.match(/void\s+TearDown\(\)\s*(?:override\s*)?\{([^{}]*(?:\{[^{}]*\}[^{}]*)*)\}/);
        
        // 提取 Mock 成员变量声明
        const mockMembers = [];
        const mockMemberPattern = /(?:std::)?(?:shared_ptr|unique_ptr|weak_ptr)?\s*<([^>]+)>\s*(\w+Mock\w*|mock\w+)\s*[;=]/gi;
        let memberMatch;
        while ((memberMatch = mockMemberPattern.exec(classBody)) !== null) {
            mockMembers.push({
                type: memberMatch[1].trim(),
                name: memberMatch[2],
                isSmartPointer: /shared_ptr|unique_ptr|weak_ptr/.test(memberMatch[0])
            });
        }
        
        // 提取 Mock 对象的初始化方式
        const initPatterns = {
            make_shared: (classBody.match(/std::make_shared\s*<[^>]+>/g) || []).length,
            make_unique: (classBody.match(/std::make_unique\s*<[^>]+>/g) || []).length,
            new_operator: (classBody.match(/new\s+\w+Mock/g) || []).length,
            direct_construct: (classBody.match(/(\w+Mock\w*)\s*\{/g) || []).length
        };
        
        // 提取测试函数中的 Mock 使用场景
        const testFunctions = [];
        const testFuncPattern = /(?:HWTEST|HWTEST_F|TEST|TEST_F)\s*\([^,]+,\s*([^,]+)\s*,\s*[^)]+\)\s*\{([^{}]*(?:\{[^{}]*\}[^{}]*)*)\}/g;
        let testMatch;
        
        while ((testMatch = testFuncPattern.exec(content)) !== null) {
            const testFuncName = testMatch[1];
            const testFuncBody = testMatch[2];
            
            // 提取该测试函数中的 Mock 使用
            const mockUsages = [];
            
            // EXPECT_CALL 使用
            const expectCallPattern = /EXPECT_CALL\s*\(\s*\*?(\w+)\s*,\s*(\w+)\s*\(([^)]*)\)\s*\)\s*\.\s*(\w+)\s*\(([^)]*)\)/g;
            let expectMatch;
            while ((expectMatch = expectCallPattern.exec(testFuncBody)) !== null) {
                mockUsages.push({
                    type: 'EXPECT_CALL',
                    mockObject: expectMatch[1],
                    method: expectMatch[2],
                    methodParams: expectMatch[3],
                    action: expectMatch[4], // WillOnce, WillRepeatedly, WillByDefault 等
                    actionParams: expectMatch[5]
                });
            }
            
            // ON_CALL 使用
            const onCallPattern = /ON_CALL\s*\(\s*\*?(\w+)\s*,\s*(\w+)\s*\(([^)]*)\)\s*\)\s*\.\s*(\w+)\s*\(([^)]*)\)/g;
            let onMatch;
            while ((onMatch = onCallPattern.exec(testFuncBody)) !== null) {
                mockUsages.push({
                    type: 'ON_CALL',
                    mockObject: onMatch[1],
                    method: onMatch[2],
                    methodParams: onMatch[3],
                    action: onMatch[4],
                    actionParams: onMatch[5]
                });
            }
            
            // Mock 对象的直接使用（调用方法）
            const mockCallPattern = /(\w+Mock\w*|mock\w+)\s*->\s*(\w+)\s*\(([^)]*)\)/gi;
            let callMatch;
            while ((callMatch = mockCallPattern.exec(testFuncBody)) !== null) {
                mockUsages.push({
                    type: 'direct_call',
                    mockObject: callMatch[1],
                    method: callMatch[2],
                    params: callMatch[3]
                });
            }
            
            if (mockUsages.length > 0) {
                testFunctions.push({
                    name: testFuncName,
                    mockUsages: mockUsages,
                    hasAssertions: /EXPECT_|ASSERT_/.test(testFuncBody),
                    hasReturnValue: /Return\(/.test(testFuncBody)
                });
            }
        }
        
        if (testClass.name || mockMembers.length > 0 || testFunctions.length > 0) {
            patterns.push({
                type: 'mock_usage_in_test',
                testClass: testClass.name || 'Unknown',
                filePath: relativePath,
                setUp: setUpMatch ? {
                    hasCode: setUpMatch[1].trim().length > 0,
                    codePreview: setUpMatch[1].substring(0, 200).trim()
                } : null,
                tearDown: tearDownMatch ? {
                    hasCode: tearDownMatch[1].trim().length > 0,
                    codePreview: tearDownMatch[1].substring(0, 200).trim()
                } : null,
                mockMembers: mockMembers,
                initPatterns: initPatterns,
                testFunctions: testFunctions,
                headerIncludes: extractHeaderDependencies(content, filePath).map(d => d.header)
            });
        }
    }
    
    // 提取全局 Mock 使用（不在类中的）
    if (testClasses.length === 0) {
        const globalMockUsages = [];
        const globalExpectCall = /EXPECT_CALL\s*\(\s*\*?(\w+)\s*,\s*(\w+)\s*\(/g;
        while ((match = globalExpectCall.exec(content)) !== null) {
            globalMockUsages.push({
                mockObject: match[1],
                method: match[2]
            });
        }
        
        if (globalMockUsages.length > 0) {
            patterns.push({
                type: 'mock_usage_global',
                filePath: relativePath,
                mockUsages: globalMockUsages
            });
        }
    }
    
    return patterns;
}

/**
 * 查找文件对应的 BUILD.gn
 */
function findBuildGn(filePath) {
    let currentDir = path.dirname(filePath);
    const maxDepth = 10;
    let depth = 0;
    
    while (depth < maxDepth && currentDir.startsWith(OH_ROOT)) {
        const buildGnPath = path.join(currentDir, 'BUILD.gn');
        if (fs.existsSync(buildGnPath)) {
            return {
                buildGnPath: path.relative(OH_ROOT, buildGnPath),
                sourceFile: path.relative(currentDir, filePath)
            };
        }
        
        const parentDir = path.dirname(currentDir);
        if (parentDir === currentDir) {
            break;
        }
        currentDir = parentDir;
        depth++;
    }
    
    return null;
}

/**
 * 提取 BUILD.gn 中的信息（包括 external_deps）- 带超时保护（120秒）
 */
function extractBuildGnInfo(buildGnPath) {
    const PARSE_TIMEOUT = 120000; // 120秒超时（毫秒）
    const startTime = Date.now();
    
    try {
        const content = fs.readFileSync(buildGnPath, 'utf-8');
        
        // 如果文件太大，直接跳过（避免处理超大文件）
        if (content.length > 500000) { // 500KB
            console.warn(`[SKIP] BUILD.gn 文件过大: ${path.relative(OH_ROOT, buildGnPath)}`);
            return null;
        }
        
        // 提取 targets
        const targets = [];
        const targetPattern = /(ohos_\w+|group|executable|action)\("([^"]+)"\)\s*\{/g;
        let match;
        
        // 限制处理的target数量，避免无限循环
        let targetCount = 0;
        const MAX_TARGETS = 1000;
        
        while ((match = targetPattern.exec(content)) !== null && targetCount < MAX_TARGETS) {
            // 检查是否超时
            if (Date.now() - startTime > PARSE_TIMEOUT) {
                console.warn(`[TIMEOUT] BUILD.gn 解析超时 (120s): ${path.relative(OH_ROOT, buildGnPath)}`);
                return null;
            }
            
            targetCount++;
            const targetType = match[1];
            const targetName = match[2];
            const targetStart = match.index;
            
            // 提取目标体内容
            let braceCount = 0;
            let targetBody = '';
            let maxIterations = Math.min(content.length - targetStart, 100000); // 限制最大迭代次数
            let iterations = 0;
            
            for (let i = targetStart; i < content.length && iterations < maxIterations; i++) {
                iterations++;
                // 每1000次迭代检查一次超时
                if (iterations % 1000 === 0 && Date.now() - startTime > PARSE_TIMEOUT) {
                    console.warn(`[TIMEOUT] BUILD.gn 解析超时 (120s): ${path.relative(OH_ROOT, buildGnPath)}`);
                    return null;
                }
                
                if (content[i] === '{') braceCount++;
                if (content[i] === '}') {
                    braceCount--;
                    if (braceCount === 0) {
                        targetBody = content.substring(targetStart, i + 1);
                        break;
                    }
                }
            }
            
            // 如果大括号匹配失败或超时，跳过这个target
            if (braceCount !== 0) {
                continue;
            }
            
            // 提取该目标的 sources
            const sourcesPattern = /sources\s*=\s*\[([^\]]+)\]/g;
            const sources = [];
            let sourceMatch;
            let sourceCount = 0;
            while ((sourceMatch = sourcesPattern.exec(targetBody)) !== null && sourceCount < 100) {
                sourceCount++;
                const sourceList = sourceMatch[1].match(/"([^"]+)"/g);
                if (sourceList) {
                    sources.push(...sourceList.map(s => s.replace(/"/g, '')));
                }
            }
            
            // 提取 external_deps
            const externalDepsPattern = /external_deps\s*=\s*\[([^\]]+)\]/g;
            const externalDeps = [];
            let depsMatch;
            let depsCount = 0;
            while ((depsMatch = externalDepsPattern.exec(targetBody)) !== null && depsCount < 100) {
                depsCount++;
                const depsList = depsMatch[1].match(/"([^"]+)"/g);
                if (depsList) {
                    externalDeps.push(...depsList.map(s => s.replace(/"/g, '')));
                }
            }
            
            // 提取 deps
            const depsPattern = /deps\s*=\s*\[([^\]]+)\]/g;
            const deps = [];
            let depMatch;
            let depCount = 0;
            while ((depMatch = depsPattern.exec(targetBody)) !== null && depCount < 100) {
                depCount++;
                const depsList = depMatch[1].match(/"([^"]+)"/g);
                if (depsList) {
                    deps.push(...depsList.map(s => s.replace(/"/g, '')));
                }
            }
            
            targets.push({
                type: targetType,
                name: targetName,
                sources,
                externalDeps,
                deps
            });
        }
        
        return {
            targets,
            hasTest: /test|unittest/i.test(content)
        };
    } catch (error) {
        return null;
    }
}

/**
 * 提取头文件依赖
 */
function extractHeaderDependencies(content, filePath) {
    const dependencies = [];
    
    // 提取 #include 语句
    const includePattern = /#include\s*[<"]([^>"]+)[>"]/g;
    let match;
    
    while ((match = includePattern.exec(content)) !== null) {
        const headerPath = match[1];
        const isSystemHeader = match[0].includes('<');
        
        dependencies.push({
            header: headerPath,
            isSystemHeader,
            type: isSystemHeader ? 'system' : 'local'
        });
    }
    
    return dependencies;
}

/**
 * 处理单个文件（带120秒超时保护）
 */
function processFile(filePath) {
    if (stats.totalFiles >= MAX_FILES_TO_SCAN) {
        return;
    }
    
    // 检查是否在跳过列表中
    const relativePathForCheck = path.relative(OH_ROOT, filePath);
    if (SKIP_FILES.includes(relativePathForCheck)) {
        console.warn(`[SKIP] 跳过文件（黑名单）: ${relativePathForCheck}`);
        return;
    }
    
    stats.totalFiles++;
    
    const FILE_PROCESS_TIMEOUT = 120000; // 120秒超时（2分钟）
    const startTime = Date.now();
    
    // 已收集的数据（用于超时后保存）
    const collectedData = {
        headerDeps: null,
        classes: [],
        globalFuncs: [],
        napiFuncs: [],
        ndkFuncs: [],
        buildGnRel: null
    };
    
    // 超时检查辅助函数
    const checkTimeout = () => {
        if (Date.now() - startTime > FILE_PROCESS_TIMEOUT) {
            const relativePath = path.relative(OH_ROOT, filePath);
            console.warn(`[TIMEOUT] 文件处理超时 (120s): ${relativePath}`);
            // 保存已收集的数据
            saveCollectedData(collectedData, relativePath, filePath);
            return true;
        }
        return false;
    };
    
    // 保存已收集数据的辅助函数
    const saveCollectedData = (data, relativePath, filePath) => {
        try {
            const ext = path.extname(filePath);
            const isTestFile = /\.test\.(h|cpp)$|test|unittest|fuzz/i.test(filePath);
            
            // 保存头文件依赖
            if (data.headerDeps && data.headerDeps.length > 0) {
                knowledgeBase.headerDependencies.push({
                    file: relativePath,
                    dependencies: data.headerDeps,
                    isTestFile,
                    partial: true // 标记为部分扫描
                });
            }
            
            // 保存类信息
            if (data.classes.length > 0) {
                knowledgeBase.classes.push(...data.classes.map(c => ({
                    ...c,
                    partial: true // 标记为部分扫描
                })));
                stats.classes += data.classes.length;
            }
            
            // 保存全局函数
            if (data.globalFuncs.length > 0) {
                knowledgeBase.functions.push(...data.globalFuncs.map(f => ({
                    ...f,
                    filePath: relativePath,
                    type: 'global',
                    partial: true // 标记为部分扫描
                })));
                stats.functions += data.globalFuncs.length;
            }
            
            // 保存 NAPI/NDK
            if (data.napiFuncs.length > 0) {
                knowledgeBase.napiPatterns.push(...data.napiFuncs.map(f => ({
                    ...f,
                    partial: true
                })));
                stats.napiFunctions += data.napiFuncs.length;
            }
            if (data.ndkFuncs.length > 0) {
                knowledgeBase.ndkPatterns.push(...data.ndkFuncs.map(f => ({
                    ...f,
                    partial: true
                })));
                stats.ndkFunctions += data.ndkFuncs.length;
            }
            
            // 保存 BUILD.gn 关系（如果有）
            if (data.buildGnRel) {
                knowledgeBase.buildGnRelations.push({
                    sourceFile: relativePath,
                    buildGnFile: data.buildGnRel.buildGnPath,
                    partial: true // 标记为部分扫描
                });
            }
            
            console.warn(`[TIMEOUT] 已保存部分扫描数据: ${relativePath} (${data.classes.length}类, ${data.globalFuncs.length}函数, ${data.headerDeps?.length || 0}依赖)`);
        } catch (e) {
            console.warn(`[TIMEOUT] 保存部分数据失败: ${relativePath} - ${e.message}`);
        }
    };
    
    try {
        if (checkTimeout()) return;
        
        const stat = fs.statSync(filePath);
        if (stat.size > MAX_FILE_SIZE) {
            // 大文件只记录基本信息
            return;
        }
        
        if (checkTimeout()) return;
        
        const content = fs.readFileSync(filePath, 'utf-8');
        
        if (checkTimeout()) return;
        
        // 跳过超过3000行的文件（避免CPU过高）
        const lineCount = (content.match(/\n/g) || []).length + 1;
        if (lineCount > 3000) {
            // 超过3000行的文件跳过，不计入统计
            stats.totalFiles--;
            return;
        }
        
        if (checkTimeout()) return;
        
        const ext = path.extname(filePath);
        const relativePath = path.relative(OH_ROOT, filePath);
        const isTestFile = /\.test\.(h|cpp)$|test|unittest|fuzz/i.test(filePath);
        
        // 提取头文件依赖（所有文件）
        if (checkTimeout()) return;
        const headerDeps = extractHeaderDependencies(content, filePath);
        collectedData.headerDeps = headerDeps;
        if (headerDeps.length > 0 && !checkTimeout()) {
            knowledgeBase.headerDependencies.push({
                file: relativePath,
                dependencies: headerDeps,
                isTestFile
            });
        }
        
        // 处理头文件
        if (ext === '.h' || ext === '.hpp') {
            stats.headerFiles++;
            
            if (checkTimeout()) return;
            const classes = extractClassInfo(content, filePath, checkTimeout);
            collectedData.classes = classes;
            if (!checkTimeout()) {
                knowledgeBase.classes.push(...classes);
                stats.classes += classes.length;
            }
            
            if (checkTimeout()) return;
            // 提取全局函数
            const globalFuncs = extractGlobalFunctions(content, filePath, checkTimeout);
            collectedData.globalFuncs = globalFuncs;
            if (!checkTimeout()) {
                knowledgeBase.functions.push(...globalFuncs.map(f => ({
                    ...f,
                    filePath: relativePath,
                    type: 'global'
                })));
            }
            
            if (checkTimeout()) return;
            // 提取 NAPI/NDK
            const napiFuncs = extractNAPI(content, filePath);
            const ndkFuncs = extractNDK(content, filePath);
            collectedData.napiFuncs = napiFuncs;
            collectedData.ndkFuncs = ndkFuncs;
            if (!checkTimeout()) {
                knowledgeBase.napiPatterns.push(...napiFuncs);
                knowledgeBase.ndkPatterns.push(...ndkFuncs);
            }
            
            if (checkTimeout()) return;
            // 查找 BUILD.gn 并提取 external_deps 关系
            const buildGnRel = findBuildGn(filePath);
            collectedData.buildGnRel = buildGnRel;
            if (buildGnRel && !checkTimeout()) {
                const fullBuildGnPath = path.join(OH_ROOT, buildGnRel.buildGnPath);
                const gnInfo = extractBuildGnInfo(fullBuildGnPath);
                
                if (gnInfo) {
                    // 找到包含该文件的 target
                    for (const target of gnInfo.targets) {
                        if (target.sources.includes(buildGnRel.sourceFile) || 
                            target.sources.some(s => s.includes(path.basename(relativePath)))) {
                            knowledgeBase.buildGnRelations.push({
                                sourceFile: relativePath,
                                buildGnFile: buildGnRel.buildGnPath,
                                target: target.name,
                                targetType: target.type
                            });
                            
                            // 建立头文件依赖与 external_deps 的映射
                            if (target.externalDeps && target.externalDeps.length > 0) {
                                knowledgeBase.buildGnExternalDeps.push({
                                    sourceFile: relativePath,
                                    buildGnFile: buildGnRel.buildGnPath,
                                    target: target.name,
                                    externalDeps: target.externalDeps,
                                    headerDependencies: headerDeps.map(d => d.header)
                                });
                            }
                            break;
                        }
                    }
                } else {
                    knowledgeBase.buildGnRelations.push({
                        sourceFile: relativePath,
                        buildGnFile: buildGnRel.buildGnPath
                    });
                }
            }
        }
        
        // 处理源文件
        if (ext === '.cpp' || ext === '.cc' || ext === '.cxx') {
            stats.sourceFiles++;
            
            if (checkTimeout()) return;
            // 提取全局函数
            const globalFuncs = extractGlobalFunctions(content, filePath, checkTimeout);
            collectedData.globalFuncs = globalFuncs;
            if (!checkTimeout()) {
                knowledgeBase.functions.push(...globalFuncs.map(f => ({
                    ...f,
                    filePath: relativePath,
                    type: 'global'
                })));
                stats.functions += globalFuncs.length;
            }
            
            if (checkTimeout()) return;
            // 提取 NAPI/NDK
            const napiFuncs = extractNAPI(content, filePath);
            const ndkFuncs = extractNDK(content, filePath);
            collectedData.napiFuncs = napiFuncs;
            collectedData.ndkFuncs = ndkFuncs;
            if (!checkTimeout()) {
                knowledgeBase.napiPatterns.push(...napiFuncs);
                knowledgeBase.ndkPatterns.push(...ndkFuncs);
                stats.napiFunctions += napiFuncs.length;
                stats.ndkFunctions += ndkFuncs.length;
            }
            
            if (checkTimeout()) return;
            // 查找 BUILD.gn 并提取 external_deps 关系
            const buildGnRel = findBuildGn(filePath);
            collectedData.buildGnRel = buildGnRel;
            if (buildGnRel && !checkTimeout()) {
                const fullBuildGnPath = path.join(OH_ROOT, buildGnRel.buildGnPath);
                const gnInfo = extractBuildGnInfo(fullBuildGnPath);
                
                if (gnInfo) {
                    // 找到包含该文件的 target
                    for (const target of gnInfo.targets) {
                        if (target.sources.includes(buildGnRel.sourceFile) || 
                            target.sources.some(s => s.includes(path.basename(relativePath)))) {
                            knowledgeBase.buildGnRelations.push({
                                sourceFile: relativePath,
                                buildGnFile: buildGnRel.buildGnPath,
                                target: target.name,
                                targetType: target.type
                            });
                            
                            // 建立源文件依赖与 external_deps 的映射
                            if (target.externalDeps && target.externalDeps.length > 0) {
                                knowledgeBase.buildGnExternalDeps.push({
                                    sourceFile: relativePath,
                                    buildGnFile: buildGnRel.buildGnPath,
                                    target: target.name,
                                    externalDeps: target.externalDeps,
                                    headerDependencies: headerDeps.map(d => d.header)
                                });
                            }
                            break;
                        }
                    }
                } else {
                    knowledgeBase.buildGnRelations.push({
                        sourceFile: relativePath,
                        buildGnFile: buildGnRel.buildGnPath
                    });
                }
            }
        }
        
        // 处理测试文件（.test.h, .test.cpp）
        if (isTestFile) {
            stats.testFiles++;
            
            const mockPatterns = extractMockPatterns(content, filePath);
            if (mockPatterns.length > 0) {
                knowledgeBase.mockPatterns.push(...mockPatterns);
                stats.mocks += mockPatterns.length;
            }
            
            // 提取测试模式
            const testPatterns = extractTestPatterns(content, filePath);
            knowledgeBase.testPatterns.push(...testPatterns);
            
            // 提取函数覆盖模式（成员函数、静态函数等）
            const coveragePatterns = extractFunctionCoveragePatterns(content, filePath);
            knowledgeBase.functionCoveragePatterns.push(...coveragePatterns);
            
            // 提取函数调用关系（测试中的函数调用）
            const callRelations = extractTestFunctionCallRelations(content, filePath);
            knowledgeBase.functionCallRelations.push(...callRelations);
            
            // 提取测试策略（不同函数类型的测试方式）
            const testStrategies = extractTestFunctionStrategies(content, filePath);
            knowledgeBase.testFunctionStrategies.push(...testStrategies);
            
            // 提取分支覆盖模式
            const branchPatterns = extractBranchCoveragePatterns(content, filePath);
            knowledgeBase.branchCoveragePatterns.push(...branchPatterns);
            
            // 提取覆盖质量指标
            const qualityMetrics = extractCoverageQualityMetrics(content, filePath);
            knowledgeBase.coverageQualityMetrics.push(...qualityMetrics);
            
            // 提取测试文件的依赖关系
            if (headerDeps.length > 0) {
                const buildGnRel = findBuildGn(filePath);
                if (buildGnRel) {
                    const fullBuildGnPath = path.join(OH_ROOT, buildGnRel.buildGnPath);
                    const gnInfo = extractBuildGnInfo(fullBuildGnPath);
                    
                    if (gnInfo) {
                        // 找到包含该测试文件的 target
                        for (const target of gnInfo.targets) {
                            if (target.sources.some(s => s.includes(path.basename(relativePath)))) {
                                knowledgeBase.testFileDependencies.push({
                                    testFile: relativePath,
                                    buildGnFile: buildGnRel.buildGnPath,
                                    target: target.name,
                                    headerDependencies: headerDeps,
                                    externalDeps: target.externalDeps || [],
                                    deps: target.deps || []
                                });
                                break;
                            }
                        }
                    }
                }
            }
        }
        
        // 处理 BUILD.gn 文件
        if (path.basename(filePath) === 'BUILD.gn') {
            stats.buildGnFiles++;
            const gnInfo = extractBuildGnInfo(filePath);
            if (gnInfo) {
                // 保存完整的 BUILD.gn 信息
                knowledgeBase.buildGnRelations.push({
                    buildGnFile: relativePath,
                    targets: gnInfo.targets.map(t => ({
                        name: t.name,
                        type: t.type,
                        sourceCount: t.sources.length,
                        externalDepsCount: t.externalDeps.length,
                        depsCount: t.deps.length
                    })),
                    isTest: gnInfo.hasTest
                });
            }
        }
        
    } catch (error) {
        // 忽略读取错误
        if (stats.totalFiles % 1000 === 0) {
            console.warn(`[WARN] 无法处理文件 ${filePath}: ${error.message}`);
        }
    }
}

/**
 * 提取测试模式（增强版：关注场景构造和覆盖目标）
 */
function extractTestPatterns(content, filePath) {
    const patterns = [];
    const relativePath = path.relative(OH_ROOT, filePath);
    
    // 检查测试框架
    const hasGTest = /gtest|HWTEST|HWTEST_F/i.test(content);
    const hasGMock = /gmock|EXPECT_CALL|ON_CALL/i.test(content);
    
    // 提取测试用例（包含更多信息）
    const testCasePattern = /(?:HWTEST|HWTEST_F|TEST|TEST_F)\s*\([^,]+,\s*([^,]+)\s*,\s*([^)]+)\)\s*\{([^{}]*(?:\{[^{}]*\}[^{}]*)*)\}/g;
    const testCases = [];
    let match;
    
    while ((match = testCasePattern.exec(content)) !== null) {
        const testFuncName = match[1];
        const testLevel = match[2].trim(); // TestSize.Level1 等
        const testBody = match[3];
        
        // 分析测试函数的场景构造
        const scenarios = {
            hasNormalCase: !/error|fail|exception|invalid/i.test(testFuncName),
            hasErrorCase: /error|fail|exception|invalid/i.test(testFuncName),
            hasBoundaryCase: /boundary|limit|max|min|edge/i.test(testFuncName),
            hasNullCase: /null|empty|zero/i.test(testFuncName) || /nullptr|null/.test(testBody),
            hasMockUsage: /EXPECT_CALL|ON_CALL/.test(testBody),
            hasAssertions: /EXPECT_|ASSERT_/.test(testBody),
            assertionTypes: {
                expectTrue: (testBody.match(/EXPECT_TRUE|ASSERT_TRUE/g) || []).length,
                expectFalse: (testBody.match(/EXPECT_FALSE|ASSERT_FALSE/g) || []).length,
                expectEq: (testBody.match(/EXPECT_EQ|ASSERT_EQ/g) || []).length,
                expectNe: (testBody.match(/EXPECT_NE|ASSERT_NE/g) || []).length,
                expectNull: (testBody.match(/EXPECT_NULL|ASSERT_NULL/g) || []).length,
                expectNotNull: (testBody.match(/EXPECT_NOT_NULL|ASSERT_NOT_NULL/g) || []).length
            },
            hasReturnValueCheck: /Return\(|ReturnRef\(|ReturnPointee\(/.test(testBody),
            hasThrow: /EXPECT_THROW|ASSERT_THROW/.test(testBody),
            hasJsonOperation: /cJSON|json|Marshal|Unmarshal/i.test(testBody),
            hasMemoryOperation: /new\s+|delete\s+|malloc|free/.test(testBody),
            hasAsyncOperation: /async|await|future|promise/i.test(testBody)
        };
        
        // 提取测试中构造的对象
        const constructedObjects = [];
        const constructPattern = /(?:std::)?(?:make_shared|make_unique)\s*<([^>]+)>\s*\(([^)]*)\)/g;
        let constructMatch;
        while ((constructMatch = constructPattern.exec(testBody)) !== null) {
            constructedObjects.push({
                type: constructMatch[1],
                params: constructMatch[2]
            });
        }
        
        testCases.push({
            name: testFuncName,
            level: testLevel,
            scenarios: scenarios,
            constructedObjects: constructedObjects,
            hasSetUp: /SetUp\(\)/.test(content.substring(0, match.index)),
            hasTearDown: /TearDown\(\)/.test(content.substring(0, match.index))
        });
    }
    
    // 提取 SetUp 和 TearDown 的使用规则
    const setUpPatterns = extractSetUpTearDownPatterns(content);
    
    // 提取测试类的结构
    const testClassPattern = /class\s+(\w+Test\w*)\s*:\s*public\s+testing::Test/g;
    const testClasses = [];
    while ((match = testClassPattern.exec(content)) !== null) {
        testClasses.push(match[1]);
    }
    
    if (testCases.length > 0 || hasGTest || hasGMock || setUpPatterns.hasSetUp || setUpPatterns.hasTearDown) {
        patterns.push({
            filePath: relativePath,
            framework: hasGTest ? 'gtest' : 'unknown',
            hasMock: hasGMock,
            testClassCount: testClasses.length,
            testClasses: testClasses,
            testCaseCount: testCases.length,
            testCases: testCases.slice(0, 50), // 保存前50个测试用例的详细信息
            setUpTearDown: setUpPatterns,
            coverageAnalysis: {
                totalTests: testCases.length,
                normalCaseTests: testCases.filter(t => t.scenarios.hasNormalCase).length,
                errorCaseTests: testCases.filter(t => t.scenarios.hasErrorCase).length,
                boundaryCaseTests: testCases.filter(t => t.scenarios.hasBoundaryCase).length,
                mockUsingTests: testCases.filter(t => t.scenarios.hasMockUsage).length,
                jsonTests: testCases.filter(t => t.scenarios.hasJsonOperation).length
            }
        });
    }
    
    return patterns;
}

/**
 * 提取函数覆盖模式（成员函数、静态函数等）
 */
function extractFunctionCoveragePatterns(content, filePath) {
    const patterns = [];
    const relativePath = path.relative(OH_ROOT, filePath);
    
    // 提取测试函数
    const testFuncPattern = /(?:HWTEST|HWTEST_F|TEST|TEST_F)\s*\([^,]+,\s*([^,]+)\s*,\s*[^)]+\)\s*\{([^{}]*(?:\{[^{}]*\}[^{}]*)*)\}/g;
    let match;
    
    while ((match = testFuncPattern.exec(content)) !== null) {
        const testFuncName = match[1];
        const testBody = match[2];
        
        // 分析测试覆盖的函数类型
        const coverage = {
            memberFunction: {
                hasPointerCall: /->\s*\w+\s*\(/.test(testBody),
                hasObjectCall: /\.\w+\s*\(/.test(testBody),
                hasSmartPointerCall: /(?:shared_ptr|unique_ptr|weak_ptr)<[^>]+>\s*->\s*\w+\s*\(/.test(testBody),
                pointerCallCount: (testBody.match(/->\s*\w+\s*\(/g) || []).length,
                objectCallCount: (testBody.match(/\.\w+\s*\(/g) || []).length
            },
            staticFunction: {
                hasStaticCall: /\w+\s*::\s*\w+\s*\(/.test(testBody),
                staticCallCount: (testBody.match(/\w+\s*::\s*\w+\s*\(/g) || []).length
            },
            globalFunction: {
                hasDirectCall: /(?:^|[^:>\.])\s*\w+\s*\(/.test(testBody),
                directCallCount: (testBody.match(/(?:^|[^:>\.])\s*\w+\s*\(/g) || []).length
            },
            constructor: {
                hasConstructorCall: /(?:make_shared|make_unique|new\s+)\w+\s*\(/.test(testBody),
                hasCopyConstruct: /=\s*\w+\s*\(/.test(testBody),
                constructorCallCount: (testBody.match(/(?:make_shared|make_unique|new\s+)\w+\s*\(/g) || []).length
            }
        };
        
        // 提取被测试的函数调用
        const testedFunctions = [];
        
        // 成员函数调用（通过指针）
        const pointerCallPattern = /(\w+)\s*->\s*(\w+)\s*\(/g;
        let callMatch;
        while ((callMatch = pointerCallPattern.exec(testBody)) !== null) {
            testedFunctions.push({
                object: callMatch[1],
                function: callMatch[2],
                callType: 'pointer_member',
                context: 'test'
            });
        }
        
        // 成员函数调用（通过对象）
        const objectCallPattern = /(\w+)\s*\.\s*(\w+)\s*\(/g;
        while ((callMatch = objectCallPattern.exec(testBody)) !== null) {
            testedFunctions.push({
                object: callMatch[1],
                function: callMatch[2],
                callType: 'object_member',
                context: 'test'
            });
        }
        
        // 静态函数调用
        const staticCallPattern = /(\w+)\s*::\s*(\w+)\s*\(/g;
        while ((callMatch = staticCallPattern.exec(testBody)) !== null) {
            testedFunctions.push({
                className: callMatch[1],
                function: callMatch[2],
                callType: 'static',
                context: 'test'
            });
        }
        
        // 全局函数调用
        const globalCallPattern = /(?:^|[^:>\.])\s*(\w+)\s*\(/g;
        while ((callMatch = globalCallPattern.exec(testBody)) !== null) {
            const funcName = callMatch[1];
            // 排除关键字
            if (!['if', 'for', 'while', 'switch', 'return', 'new', 'delete', 'sizeof', 'EXPECT', 'ASSERT'].includes(funcName)) {
                testedFunctions.push({
                    function: funcName,
                    callType: 'global',
                    context: 'test'
                });
            }
        }
        
        // 分析被测试函数的调用链（包括间接调用）
        const callChainAnalysis = analyzeFunctionCallChain(testBody, content, relativePath);
        
        if (testedFunctions.length > 0 || coverage.memberFunction.hasPointerCall || coverage.staticFunction.hasStaticCall || callChainAnalysis.hasIndirectCall) {
            patterns.push({
                testFile: relativePath,
                testFunction: testFuncName,
                coverage: coverage,
                testedFunctions: testedFunctions,
                sameFileCalls: extractSameFileCalls(content, testBody, relativePath),
                sameModuleCalls: extractSameModuleCalls(content, testBody, relativePath),
                callChainAnalysis: callChainAnalysis
            });
        }
    }
    
    return patterns;
}

/**
 * 提取同文件函数调用
 */
function extractSameFileCalls(fullContent, testBody, filePath) {
    const sameFileCalls = [];
    
    // 提取文件中定义的函数
    const definedFunctions = [];
    const funcDefPattern = /(?:^|\n)(?:\w+\s+)*(\w+)\s*\([^)]*\)\s*\{/g;
    let match;
    
    while ((match = funcDefPattern.exec(fullContent)) !== null) {
        const funcName = match[1];
        if (!['if', 'for', 'while', 'switch', 'return', 'new', 'delete'].includes(funcName)) {
            definedFunctions.push(funcName);
        }
    }
    
    // 检查测试体中是否调用了同文件的函数
    for (const funcName of definedFunctions) {
        if (testBody.includes(`${funcName}(`)) {
            sameFileCalls.push(funcName);
        }
    }
    
    return sameFileCalls;
}

/**
 * 提取同模块函数调用（基于目录结构，扫描同目录下的源文件）
 */
function extractSameModuleCalls(fullContent, testBody, filePath) {
    const sameModuleCalls = [];
    
    try {
        // 判断模块目录（test目录的父目录通常是模块目录）
        const testDir = path.dirname(filePath);
        const moduleDir = path.dirname(testDir); // 上一级目录
        
        // 扫描同模块目录下的源文件（.cpp, .h）
        const moduleFiles = [];
        if (fs.existsSync(moduleDir)) {
            const scanModuleDir = (dir, depth = 0) => {
                if (depth > 3) return; // 最多扫描3层
                
                try {
                    const entries = fs.readdirSync(dir, { withFileTypes: true });
                    for (const entry of entries) {
                        if (entry.isDirectory() && !['test', 'tests', 'unittest', 'fuzztest', 'mock', 'include'].includes(entry.name)) {
                            scanModuleDir(path.join(dir, entry.name), depth + 1);
                        } else if (entry.isFile() && /\.(cpp|h|hpp)$/.test(entry.name)) {
                            moduleFiles.push(path.join(dir, entry.name));
                        }
                    }
                } catch (e) {
                    // 忽略权限错误
                }
            };
            
            scanModuleDir(moduleDir);
        }
        
        // 从模块文件中提取函数定义
        const moduleFunctions = new Set();
        for (const moduleFile of moduleFiles.slice(0, 50)) { // 限制扫描数量
            try {
                const moduleContent = fs.readFileSync(moduleFile, 'utf-8');
                // 提取函数定义
                const funcDefPattern = /(?:^|\n)(?:\w+\s+)*(\w+)\s*\([^)]*\)\s*\{/g;
                let match;
                while ((match = funcDefPattern.exec(moduleContent)) !== null) {
                    const funcName = match[1];
                    if (!['if', 'for', 'while', 'switch', 'return', 'new', 'delete'].includes(funcName)) {
                        moduleFunctions.add(funcName);
                    }
                }
            } catch (e) {
                // 忽略读取错误
            }
        }
        
        // 检查测试体中是否调用了同模块的函数
        for (const funcName of moduleFunctions) {
            if (testBody.includes(`${funcName}(`)) {
                sameModuleCalls.push({
                    function: funcName,
                    module: path.basename(moduleDir)
                });
            }
        }
    } catch (e) {
        // 忽略错误
    }
    
    return sameModuleCalls;
}

/**
 * 提取测试函数调用关系（增强版：包含完整调用链分析）
 */
function extractTestFunctionCallRelations(content, filePath) {
    const relations = [];
    const relativePath = path.relative(OH_ROOT, filePath);
    
    // 提取测试函数及其调用的函数
    const testFuncPattern = /(?:HWTEST|HWTEST_F|TEST|TEST_F)\s*\([^,]+,\s*([^,]+)\s*,\s*[^)]+\)\s*\{([^{}]*(?:\{[^{}]*\}[^{}]*)*)\}/g;
    let match;
    
    while ((match = testFuncPattern.exec(content)) !== null) {
        const testFuncName = match[1];
        const testBody = match[2];
        
        // 提取函数调用链（增强版）
        const callChain = extractCallChain(testBody);
        
        // 分析调用关系
        const callAnalysis = analyzeFunctionCallChain(testBody, content, relativePath);
        
        if (callChain.length > 0 || callAnalysis.hasIndirectCall) {
            relations.push({
                testFile: relativePath,
                testFunction: testFuncName,
                callChain: callChain,
                callDepth: callAnalysis.callDepth,
                directCalls: callAnalysis.directCalls,
                indirectCalls: callAnalysis.indirectCalls,
                pointerCallChain: callAnalysis.pointerCallChain,
                staticCallChain: callAnalysis.staticCallChain,
                hasSameFileCall: extractSameFileCalls(content, testBody, relativePath).length > 0,
                hasSameModuleCall: extractSameModuleCalls(content, testBody, relativePath).length > 0
            });
        }
    }
    
    return relations;
}

/**
 * 提取调用链（增强版：包含调用类型和上下文）
 */
function extractCallChain(testBody) {
    const calls = [];
    const seen = new Set();
    
    // 提取所有函数调用（包括不同调用方式）
    const callPatterns = [
        // 指针调用：obj->method(...)
        { pattern: /(\w+)\s*->\s*(\w+)\s*\(/g, type: 'pointer_member' },
        // 对象调用：obj.method(...)
        { pattern: /(\w+)\s*\.\s*(\w+)\s*\(/g, type: 'object_member' },
        // 静态调用：Class::method(...)
        { pattern: /(\w+)\s*::\s*(\w+)\s*\(/g, type: 'static_member' },
        // 直接调用：function(...)
        { pattern: /(?:^|[^:>\.])\s*(\w+)\s*\(/g, type: 'direct' }
    ];
    
    for (const { pattern, type } of callPatterns) {
        let match;
        while ((match = pattern.exec(testBody)) !== null) {
            const funcName = match[2] || match[1];
            const key = `${type}_${funcName}`;
            
            if (!seen.has(key) && !['if', 'for', 'while', 'switch', 'return', 'new', 'delete', 'EXPECT', 'ASSERT', 'ON_CALL'].includes(funcName)) {
                calls.push({
                    function: funcName,
                    callType: type,
                    object: match[1] && type !== 'direct' ? match[1] : null,
                    className: type === 'static_member' ? match[1] : null
                });
                seen.add(key);
            }
        }
    }
    
    return calls;
}

/**
 * 分析函数调用链（包括间接调用）
 */
function analyzeFunctionCallChain(testBody, fullContent, filePath) {
    const analysis = {
        directCalls: [],
        indirectCalls: [],
        hasIndirectCall: false,
        callDepth: 0,
        pointerCallChain: [],
        staticCallChain: []
    };
    
    // 提取直接调用
    const directCalls = extractCallChain(testBody);
    analysis.directCalls = directCalls;
    
    // 分析间接调用（被调函数内部又调用了其他函数）
    for (const call of directCalls) {
        if (call.callType === 'pointer_member' || call.callType === 'object_member') {
            analysis.pointerCallChain.push({
                object: call.object,
                function: call.function,
                callType: call.callType
            });
        } else if (call.callType === 'static_member') {
            analysis.staticCallChain.push({
                className: call.className,
                function: call.function
            });
        }
        
        // 尝试在文件中查找被调函数的定义，分析其内部调用
        const funcDefPattern = new RegExp(`(?:\\w+\\s+)*${call.function}\\s*\\([^)]*\\)\\s*\\{([^{}]*(?:\\{[^{}]*\\}[^{}]*)*)\\}`);
        const funcMatch = fullContent.match(funcDefPattern);
        
        if (funcMatch) {
            const funcBody = funcMatch[1];
            const indirectCalls = extractCallChain(funcBody);
            
            if (indirectCalls.length > 0) {
                analysis.hasIndirectCall = true;
                analysis.indirectCalls.push({
                    directFunction: call.function,
                    indirectCalls: indirectCalls
                });
            }
        }
    }
    
    // 计算调用深度（最大嵌套深度）
    analysis.callDepth = calculateMaxCallDepth(analysis.directCalls, analysis.indirectCalls);
    
    return analysis;
}

/**
 * 计算最大调用深度
 */
function calculateMaxCallDepth(directCalls, indirectCalls) {
    let maxDepth = directCalls.length;
    
    for (const indirect of indirectCalls) {
        const depth = 1 + indirect.indirectCalls.length;
        if (depth > maxDepth) {
            maxDepth = depth;
        }
    }
    
    return maxDepth;
}

/**
 * 计算调用深度（已移至 analyzeFunctionCallChain 中，保留此函数以兼容）
 */
function calculateCallDepth(callChain) {
    return callChain.length;
}

/**
 * 提取测试函数策略（不同函数类型的测试方式）
 */
function extractTestFunctionStrategies(content, filePath) {
    const strategies = [];
    const relativePath = path.relative(OH_ROOT, filePath);
    
    // 提取测试函数
    const testFuncPattern = /(?:HWTEST|HWTEST_F|TEST|TEST_F)\s*\([^,]+,\s*([^,]+)\s*,\s*[^)]+\)\s*\{([^{}]*(?:\{[^{}]*\}[^{}]*)*)\}/g;
    let match;
    
    while ((match = testFuncPattern.exec(content)) !== null) {
        const testFuncName = match[1];
        const testBody = match[2];
        
        // 分析覆盖场景（从测试函数名和内容推断）
        const coverage = {
            memberFunction: {
                hasPointerCall: /->\s*\w+\s*\(/.test(testBody),
                hasObjectCall: /\.\w+\s*\(/.test(testBody),
                hasSmartPointerCall: /(?:shared_ptr|unique_ptr|weak_ptr)<[^>]+>\s*->\s*\w+\s*\(/.test(testBody),
                pointerCallCount: (testBody.match(/->\s*\w+\s*\(/g) || []).length
            },
            staticFunction: {
                hasStaticCall: /\w+\s*::\s*\w+\s*\(/.test(testBody)
            },
            globalFunction: {
                hasDirectCall: /(?:^|[^:>\.])\s*\w+\s*\(/.test(testBody)
            },
            constructor: {
                hasConstructorCall: /(?:make_shared|make_unique|new\s+)\w+\s*\(/.test(testBody)
            }
        };
        
        // 分析测试策略
        const strategy = {
            testFunction: testFuncName,
            testFile: relativePath,
            strategies: {
                // 成员函数测试策略
                memberFunctionStrategy: {
                    usesPointer: /->\s*\w+\s*\(/.test(testBody),
                    usesObject: /\.\w+\s*\(/.test(testBody),
                    usesSmartPointer: /(?:shared_ptr|unique_ptr|weak_ptr)/.test(testBody),
                    pointerType: extractPointerType(testBody),
                    pointerCallCount: coverage.memberFunction.pointerCallCount
                },
                // 静态函数测试策略
                staticFunctionStrategy: {
                    usesStaticCall: /\w+\s*::\s*\w+\s*\(/.test(testBody),
                    staticCallPattern: extractStaticCallPattern(testBody)
                },
                // 全局函数测试策略
                globalFunctionStrategy: {
                    usesDirectCall: /(?:^|[^:>\.])\s*\w+\s*\(/.test(testBody),
                    hasNamespace: /::/.test(testBody)
                },
                // 构造函数测试策略
                constructorStrategy: {
                    usesMakeShared: /make_shared/.test(testBody),
                    usesMakeUnique: /make_unique/.test(testBody),
                    usesNew: /new\s+\w+/.test(testBody),
                    hasParams: /\(\s*[^)]+\s*\)/.test(testBody)
                },
                // 同文件/同模块函数调用策略
                sameFileModuleStrategy: {
                    hasSameFileCall: extractSameFileCalls(content, testBody, relativePath).length > 0,
                    sameFileCalls: extractSameFileCalls(content, testBody, relativePath),
                    hasSameModuleCall: extractSameModuleCalls(content, testBody, relativePath).length > 0,
                    sameModuleCalls: extractSameModuleCalls(content, testBody, relativePath),
                    callChainAnalysis: analyzeFunctionCallChain(testBody, content, relativePath)
                },
                // 覆盖策略分析
                coverageStrategy: {
                    coversMemberFunction: coverage.memberFunction.hasPointerCall || coverage.memberFunction.hasObjectCall,
                    coversStaticFunction: coverage.staticFunction.hasStaticCall,
                    coversGlobalFunction: coverage.globalFunction.hasDirectCall,
                    coversConstructor: coverage.constructor.hasConstructorCall,
                    usesPointerCall: coverage.memberFunction.hasPointerCall,
                    usesSmartPointer: coverage.memberFunction.hasSmartPointerCall,
                    pointerCallCount: coverage.memberFunction.pointerCallCount,
                    // 覆盖分支分析
                    branchCoverage: {
                        hasIfBranch: /if\s*\(/.test(testBody),
                        hasSwitchBranch: /switch\s*\(/.test(testBody),
                        hasLoopBranch: /(?:for|while)\s*\(/.test(testBody),
                        hasExceptionBranch: /try|catch|throw/.test(testBody)
                    }
                }
            }
        };
        
        strategies.push(strategy);
    }
    
    return strategies;
}

/**
 * 提取指针类型
 */
function extractPointerType(testBody) {
    if (testBody.includes('shared_ptr')) {
        return 'shared_ptr';
    } else if (testBody.includes('unique_ptr')) {
        return 'unique_ptr';
    } else if (testBody.includes('weak_ptr')) {
        return 'weak_ptr';
    } else if (testBody.includes('->')) {
        return 'raw_pointer';
    }
    return 'none';
}

/**
 * 提取静态调用模式
 */
function extractStaticCallPattern(testBody) {
    const patterns = [];
    const staticCallPattern = /(\w+)\s*::\s*(\w+)\s*\(/g;
    let match;
    
    while ((match = staticCallPattern.exec(testBody)) !== null) {
        patterns.push({
            className: match[1],
            function: match[2]
        });
    }
    
    return patterns;
}

/**
 * 提取分支覆盖模式（if/switch/循环/异常等）
 */
function extractBranchCoveragePatterns(content, filePath) {
    const patterns = [];
    const relativePath = path.relative(OH_ROOT, filePath);
    
    // 提取测试函数
    const testFuncPattern = /(?:HWTEST|HWTEST_F|TEST|TEST_F)\s*\([^,]+,\s*([^,]+)\s*,\s*[^)]+\)\s*\{([^{}]*(?:\{[^{}]*\}[^{}]*)*)\}/g;
    let match;
    
    while ((match = testFuncPattern.exec(content)) !== null) {
        const testFuncName = match[1];
        const testBody = match[2];
        
        // 分析分支覆盖
        const branchCoverage = {
            // if 分支覆盖
            ifBranches: {
                hasIf: /if\s*\(/.test(testBody),
                ifCount: (testBody.match(/if\s*\(/g) || []).length,
                hasElse: /else\s*\{/.test(testBody),
                hasElseIf: /else\s+if\s*\(/.test(testBody),
                hasNestedIf: /if\s*\([^)]*\)\s*\{[^}]*if\s*\(/.test(testBody)
            },
            // switch 分支覆盖
            switchBranches: {
                hasSwitch: /switch\s*\(/.test(testBody),
                switchCount: (testBody.match(/switch\s*\(/g) || []).length,
                caseCount: (testBody.match(/case\s+[^:]+:/g) || []).length,
                hasDefault: /default\s*:/.test(testBody),
                hasBreak: /break\s*;/.test(testBody)
            },
            // 循环分支覆盖
            loopBranches: {
                hasFor: /for\s*\(/.test(testBody),
                hasWhile: /while\s*\(/.test(testBody),
                hasDoWhile: /do\s*\{/.test(testBody),
                hasContinue: /continue\s*;/.test(testBody),
                hasBreak: /break\s*;/.test(testBody),
                hasNestedLoop: /(?:for|while)\s*\([^)]*\)\s*\{[^}]*(?:for|while)\s*\(/.test(testBody)
            },
            // 异常分支覆盖
            exceptionBranches: {
                hasTry: /try\s*\{/.test(testBody),
                hasCatch: /catch\s*\(/.test(testBody),
                hasThrow: /throw\s+/.test(testBody),
                hasExceptionTest: /EXPECT_THROW|ASSERT_THROW/.test(testBody),
                catchCount: (testBody.match(/catch\s*\(/g) || []).length
            },
            // 空值检查分支
            nullCheckBranches: {
                hasNullCheck: /(?:==|!=)\s*nullptr|(?:==|!=)\s*NULL|(?:==|!=)\s*null/.test(testBody),
                hasNotNullCheck: /!=\s*nullptr|!=\s*NULL|!=\s*null/.test(testBody),
                hasEmptyCheck: /\.empty\(\)|\.isEmpty\(\)/.test(testBody)
            },
            // 边界值检查
            boundaryBranches: {
                hasSizeCheck: /\.size\(\)|\.length\(\)|\.count\(\)/.test(testBody),
                hasMaxCheck: /max|MAX|maximum/.test(testBody),
                hasMinCheck: /min|MIN|minimum/.test(testBody),
                hasZeroCheck: /(?:==|!=)\s*0|(?:==|!=)\s*0\.0/.test(testBody)
            },
            // 返回值检查分支
            returnValueBranches: {
                hasReturnCheck: /return\s+/.test(testBody),
                hasReturnValueCheck: /EXPECT_EQ|ASSERT_EQ|EXPECT_NE|ASSERT_NE/.test(testBody),
                hasReturnNullCheck: /EXPECT_NULL|ASSERT_NULL|EXPECT_NOT_NULL|ASSERT_NOT_NULL/.test(testBody),
                hasBoolCheck: /EXPECT_TRUE|ASSERT_TRUE|EXPECT_FALSE|ASSERT_FALSE/.test(testBody)
            }
        };
        
        // 计算分支覆盖率估算
        const branchCoverageScore = calculateBranchCoverageScore(branchCoverage);
        
        if (branchCoverageScore > 0) {
            patterns.push({
                testFile: relativePath,
                testFunction: testFuncName,
                branchCoverage: branchCoverage,
                coverageScore: branchCoverageScore,
                totalBranchTypes: countBranchTypes(branchCoverage)
            });
        }
    }
    
    return patterns;
}

/**
 * 计算分支覆盖率评分
 */
function calculateBranchCoverageScore(branchCoverage) {
    let score = 0;
    
    // if 分支
    if (branchCoverage.ifBranches.hasIf) score += 2;
    if (branchCoverage.ifBranches.hasElse) score += 1;
    if (branchCoverage.ifBranches.hasElseIf) score += 1;
    
    // switch 分支
    if (branchCoverage.switchBranches.hasSwitch) score += 2;
    score += Math.min(branchCoverage.switchBranches.caseCount, 5); // 最多5分
    if (branchCoverage.switchBranches.hasDefault) score += 1;
    
    // 循环分支
    if (branchCoverage.loopBranches.hasFor || branchCoverage.loopBranches.hasWhile) score += 1;
    if (branchCoverage.loopBranches.hasContinue || branchCoverage.loopBranches.hasBreak) score += 1;
    
    // 异常分支
    if (branchCoverage.exceptionBranches.hasTry) score += 2;
    score += branchCoverage.exceptionBranches.catchCount;
    if (branchCoverage.exceptionBranches.hasExceptionTest) score += 2;
    
    // 空值检查
    if (branchCoverage.nullCheckBranches.hasNullCheck || branchCoverage.nullCheckBranches.hasNotNullCheck) score += 1;
    
    // 边界值检查
    if (branchCoverage.boundaryBranches.hasSizeCheck) score += 1;
    if (branchCoverage.boundaryBranches.hasMaxCheck || branchCoverage.boundaryBranches.hasMinCheck) score += 1;
    
    // 返回值检查
    if (branchCoverage.returnValueBranches.hasReturnValueCheck) score += 2;
    if (branchCoverage.returnValueBranches.hasBoolCheck) score += 1;
    
    return score;
}

/**
 * 统计分支类型数量
 */
function countBranchTypes(branchCoverage) {
    let count = 0;
    if (branchCoverage.ifBranches.hasIf) count++;
    if (branchCoverage.switchBranches.hasSwitch) count++;
    if (branchCoverage.loopBranches.hasFor || branchCoverage.loopBranches.hasWhile) count++;
    if (branchCoverage.exceptionBranches.hasTry) count++;
    if (branchCoverage.nullCheckBranches.hasNullCheck || branchCoverage.nullCheckBranches.hasNotNullCheck) count++;
    if (branchCoverage.boundaryBranches.hasSizeCheck || branchCoverage.boundaryBranches.hasMaxCheck || branchCoverage.boundaryBranches.hasMinCheck) count++;
    return count;
}

/**
 * 提取覆盖质量指标
 */
function extractCoverageQualityMetrics(content, filePath) {
    const metrics = [];
    const relativePath = path.relative(OH_ROOT, filePath);
    
    // 提取测试函数
    const testFuncPattern = /(?:HWTEST|HWTEST_F|TEST|TEST_F)\s*\([^,]+,\s*([^,]+)\s*,\s*[^)]+\)\s*\{([^{}]*(?:\{[^{}]*\}[^{}]*)*)\}/g;
    let match;
    
    while ((match = testFuncPattern.exec(content)) !== null) {
        const testFuncName = match[1];
        const testBody = match[2];
        
        // 质量指标
        const quality = {
            // 断言质量
            assertions: {
                count: (testBody.match(/EXPECT_|ASSERT_/g) || []).length,
                types: {
                    expectEq: (testBody.match(/EXPECT_EQ|ASSERT_EQ/g) || []).length,
                    expectNe: (testBody.match(/EXPECT_NE|ASSERT_NE/g) || []).length,
                    expectTrue: (testBody.match(/EXPECT_TRUE|ASSERT_TRUE/g) || []).length,
                    expectFalse: (testBody.match(/EXPECT_FALSE|ASSERT_FALSE/g) || []).length,
                    expectNull: (testBody.match(/EXPECT_NULL|ASSERT_NULL/g) || []).length,
                    expectNotNull: (testBody.match(/EXPECT_NOT_NULL|ASSERT_NOT_NULL/g) || []).length,
                    expectThrow: (testBody.match(/EXPECT_THROW|ASSERT_THROW/g) || []).length
                },
                hasMultipleAssertions: (testBody.match(/EXPECT_|ASSERT_/g) || []).length > 1,
                hasComprehensiveAssertions: (testBody.match(/EXPECT_|ASSERT_/g) || []).length > 3
            },
            // 测试场景多样性
            scenarios: {
                hasNormalCase: !/error|fail|exception|invalid/i.test(testFuncName),
                hasErrorCase: /error|fail|exception|invalid/i.test(testFuncName),
                hasBoundaryCase: /boundary|limit|max|min|edge/i.test(testFuncName),
                hasNullCase: /null|empty|zero/i.test(testFuncName),
                scenarioCount: countScenarios(testFuncName, testBody)
            },
            // 对象构造和使用
            objectUsage: {
                constructionCount: (testBody.match(/(?:make_shared|make_unique|new\s+)/g) || []).length,
                hasSmartPointer: /(?:shared_ptr|unique_ptr|weak_ptr)/.test(testBody),
                hasMultipleObjects: (testBody.match(/std::(?:make_shared|make_unique)/g) || []).length > 1
            },
            // Mock 使用质量
            mockUsage: {
                hasMock: /EXPECT_CALL|ON_CALL|MOCK_METHOD/.test(testBody),
                mockCallCount: (testBody.match(/EXPECT_CALL|ON_CALL/g) || []).length,
                hasReturnValue: /Return\(/.test(testBody),
                hasAction: /WillOnce|WillRepeatedly|WillByDefault/.test(testBody)
            },
            // 代码质量
            codeQuality: {
                hasLogging: /GTEST_LOG_|HILOG|LOGI|LOGD/.test(testBody),
                hasComments: /\/\/|\/\*/.test(testBody),
                codeLength: testBody.length,
                hasComplexLogic: /(?:if|switch|for|while)\s*\([^)]*\)\s*\{[^}]{100,}/.test(testBody)
            }
        };
        
        // 计算质量评分
        const qualityScore = calculateQualityScore(quality);
        
        metrics.push({
            testFile: relativePath,
            testFunction: testFuncName,
            quality: quality,
            qualityScore: qualityScore,
            isHighQuality: qualityScore >= 15 // 高质量阈值
        });
    }
    
    return metrics;
}

/**
 * 计算质量评分
 */
function calculateQualityScore(quality) {
    let score = 0;
    
    // 断言质量（最多5分）
    score += Math.min(quality.assertions.count, 5);
    if (quality.assertions.hasComprehensiveAssertions) score += 2;
    
    // 场景多样性（最多5分）
    score += quality.scenarios.scenarioCount;
    
    // 对象使用（最多3分）
    if (quality.objectUsage.hasSmartPointer) score += 1;
    if (quality.objectUsage.constructionCount > 0) score += 1;
    if (quality.objectUsage.hasMultipleObjects) score += 1;
    
    // Mock 使用（最多3分）
    if (quality.mockUsage.hasMock && quality.mockUsage.hasReturnValue) score += 2;
    if (quality.mockUsage.hasAction) score += 1;
    
    // 代码质量（最多2分）
    if (quality.codeQuality.hasLogging) score += 1;
    if (quality.codeQuality.codeLength > 100 && quality.codeQuality.codeLength < 500) score += 1;
    
    return score;
}

/**
 * 统计测试场景数量
 */
function countScenarios(testFuncName, testBody) {
    let count = 0;
    if (!/error|fail|exception|invalid/i.test(testFuncName)) count++; // 正常场景
    if (/error|fail|exception|invalid/i.test(testFuncName)) count++; // 错误场景
    if (/boundary|limit|max|min|edge/i.test(testFuncName)) count++; // 边界场景
    if (/null|empty|zero/i.test(testFuncName) || /nullptr|null/.test(testBody)) count++; // 空值场景
    return count;
}

/**
 * 提取 SetUp 和 TearDown 的使用规则
 */
function extractSetUpTearDownPatterns(content) {
    const patterns = {
        hasSetUp: /void\s+SetUp\(\)/.test(content),
        hasTearDown: /void\s+TearDown\(\)/.test(content),
        setUpPatterns: [],
        tearDownPatterns: []
    };
    
    // 提取 SetUp 的实现模式
    const setUpPattern = /void\s+SetUp\(\)\s*(?:override\s*)?\{([^{}]*(?:\{[^{}]*\}[^{}]*)*)\}/g;
    let match;
    
    while ((match = setUpPattern.exec(content)) !== null) {
        const setUpBody = match[1];
        patterns.setUpPatterns.push({
            hasMockInit: /make_shared|make_unique|new\s+\w+Mock/.test(setUpBody),
            hasInstanceInit: /instance_|obj_|target_/.test(setUpBody),
            hasMemberInit: /member_|var_/.test(setUpBody),
            hasConfigInit: /config|Config|setting|Setting/.test(setUpBody),
            hasLoggerInit: /logger|Logger|log|Log/.test(setUpBody),
            initCount: (setUpBody.match(/=\s*(?:std::)?(?:make_shared|make_unique)/g) || []).length,
            codePreview: setUpBody.substring(0, 300).trim()
        });
    }
    
    // 提取 TearDown 的实现模式
    const tearDownPattern = /void\s+TearDown\(\)\s*(?:override\s*)?\{([^{}]*(?:\{[^{}]*\}[^{}]*)*)\}/g;
    
    while ((match = tearDownPattern.exec(content)) !== null) {
        const tearDownBody = match[1];
        patterns.tearDownPatterns.push({
            hasCleanup: /reset|clear|delete|free|cleanup/i.test(tearDownBody),
            hasReset: /\.reset\(\)/.test(tearDownBody),
            hasNullptr: /=\s*nullptr/.test(tearDownBody),
            hasDelete: /delete\s+/.test(tearDownBody),
            codePreview: tearDownBody.substring(0, 300).trim()
        });
    }
    
    return patterns;
}

/**
 * 主函数
 */
async function main() {
    console.log('🚀 开始生成 OpenHarmony 知识库...');
    console.log(`📁 扫描目录: ${OH_ROOT}`);
    console.log(`📦 输出目录: ${OUTPUT_DIR}`);
    
    // 确保输出目录存在
    if (!fs.existsSync(OUTPUT_DIR)) {
        fs.mkdirSync(OUTPUT_DIR, { recursive: true });
    }
    
    // 加载已处理的文件列表（断点续传）
    if (fs.existsSync(PROCESSED_FILES_FILE)) {
        try {
            const processedData = JSON.parse(fs.readFileSync(PROCESSED_FILES_FILE, 'utf-8'));
            if (Array.isArray(processedData)) {
                processedData.forEach(file => PROCESSED_FILES_SET.add(file));
                // 初始化统计：已处理的文件数作为起始计数
                stats.totalFiles = PROCESSED_FILES_SET.size;
                console.log(`📋 断点续传: 已加载 ${PROCESSED_FILES_SET.size} 个已处理文件`);
                console.log(`📊 累计文件数: ${stats.totalFiles}`);
            }
        } catch (e) {
            console.warn(`⚠️ 加载已处理文件列表失败: ${e.message}`);
        }
    }
    
    // 扫描文件
    console.log('📖 开始扫描文件...');
    const startTime = Date.now();
    
    // 跟踪顶级目录扫描状态
    let currentTopLevelDir = '';
    let foundationCompleted = false;
    let foundationStartFile = 0;
    let foundationEndFile = 0;
    const stopFlag = { shouldStop: false }; // 停止标志对象，用于跨递归层传递
    
    scanDirectory(OH_ROOT, (filePath) => {
        // 如果foundation已完成，停止扫描
        if (foundationCompleted && stopFlag.shouldStop) {
            return true; // 返回true表示停止扫描
        }
        
        if (stats.totalFiles >= MAX_FILES_TO_SCAN) {
            console.log(`\n⚠️  达到最大文件扫描限制: ${MAX_FILES_TO_SCAN}`);
            console.log(`   最后处理的文件: ${stats.lastProcessedFile}`);
            console.log(`   最后处理的目录: ${stats.lastProcessedDirectory}`);
            return;
        }
        
        const relativePath = path.relative(OH_ROOT, filePath);
        
        // 断点续传：跳过已处理的文件
        if (PROCESSED_FILES_SET.has(relativePath)) {
            return; // 跳过已处理的文件
        }
        
        // 检查是否在跳过目录中
        for (const skipDir of SKIP_DIRS) {
            if (relativePath.startsWith(skipDir)) {
                return; // 跳过整个目录
            }
        }
        
        stats.totalFiles++;
        stats.lastProcessedFile = relativePath;
        stats.lastProcessedDirectory = path.dirname(relativePath);
        
        // 每处理100个文件输出一次进度到文件（更实时）
        if (stats.totalFiles % 100 === 0) {
            const progressFile = path.join(__dirname, '../.knowledge-base-progress.json');
            const progressInfo = {
                totalFiles: stats.totalFiles,
                lastProcessedFile: stats.lastProcessedFile,
                lastProcessedDirectory: stats.lastProcessedDirectory,
                currentTopLevelDir: currentTopLevelDir || '未知',
                timestamp: new Date().toISOString(),
                memoryMB: Math.round(process.memoryUsage().heapUsed / 1024 / 1024)
            };
            try {
                fs.writeFileSync(progressFile, JSON.stringify(progressInfo, null, 2), 'utf-8');
            } catch (e) {
                // 忽略写入错误
            }
        }
        
        // 每处理1000个文件保存一次批次数据（避免内存过大）
        if (stats.totalFiles % BATCH_SAVE_INTERVAL === 0) {
            const batchNumber = Math.floor(stats.totalFiles / BATCH_SAVE_INTERVAL);
            if (saveBatchToTempFile(batchNumber)) {
                console.log(`[BATCH] 已保存批次 ${batchNumber} (文件数: ${stats.totalFiles}, 内存: ${Math.round(process.memoryUsage().heapUsed / 1024 / 1024)}MB)`);
            }
        }
        
        // 检测顶级目录变化（第一级目录，如 foundation、base、arkcompiler 等）
        const pathParts = relativePath.split(path.sep);
        const topLevelDir = pathParts[0];
        
        // 如果检测到新顶级目录，检查是否完成 foundation
        if (topLevelDir !== currentTopLevelDir && currentTopLevelDir !== '') {
            // 如果之前正在扫描 foundation，现在切换到其他目录，说明 foundation 已完成
            if (currentTopLevelDir === 'foundation' && !foundationCompleted) {
                foundationCompleted = true;
                foundationEndFile = stats.totalFiles - 1;
                const foundationFileCount = foundationEndFile - foundationStartFile + 1;
                console.log(`\n🎉 ===========================================`);
                console.log(`🎉 foundation 目录扫描完成！`);
                console.log(`🎉 文件数: ${foundationFileCount} 个`);
                console.log(`🎉 起始文件编号: ${foundationStartFile}`);
                console.log(`🎉 结束文件编号: ${foundationEndFile}`);
                console.log(`🎉 最后处理的文件: ${stats.lastProcessedFile}`);
                console.log(`🎉 ===========================================`);
                console.log(`\n🛑 停止扫描（foundation目录已完成）\n`);
                stopFlag.shouldStop = true;
                return true; // 返回true停止扫描
            }
        }
        
        // 如果开始扫描 foundation 目录，记录起始文件编号
        if (topLevelDir === 'foundation' && currentTopLevelDir !== 'foundation' && !foundationCompleted) {
            foundationStartFile = stats.totalFiles;
            console.log(`\n📂 开始扫描 foundation 目录... (文件编号: ${foundationStartFile})\n`);
        }
        
        currentTopLevelDir = topLevelDir;
        
        processFile(filePath);
        
        // 标记文件已处理（断点续传）
        PROCESSED_FILES_SET.add(relativePath);
        
        // 每1000个文件保存一次已处理文件列表（避免丢失进度）
        if (PROCESSED_FILES_SET.size % 1000 === 0) {
            try {
                const processedArray = Array.from(PROCESSED_FILES_SET);
                fs.writeFileSync(PROCESSED_FILES_FILE, JSON.stringify(processedArray, null, 2), 'utf-8');
            } catch (e) {
                // 忽略写入错误
            }
        }
        
        // 如果设置了停止标志，返回true停止扫描
        if (stopFlag.shouldStop) {
            return true;
        }
    }, MAX_SCAN_DEPTH, 0, stopFlag);
    
    // 扫描完成后，保存最终已处理文件列表
    try {
        const processedArray = Array.from(PROCESSED_FILES_SET);
        fs.writeFileSync(PROCESSED_FILES_FILE, JSON.stringify(processedArray, null, 2), 'utf-8');
        console.log(`\n✅ 已保存已处理文件列表 (${processedArray.length} 个文件)`);
    } catch (e) {
        console.warn(`⚠️ 保存已处理文件列表失败: ${e.message}`);
    }
    
    // 扫描完成后，如果还在 foundation 目录中，也报告完成
    if (currentTopLevelDir === 'foundation' && !foundationCompleted) {
        foundationCompleted = true;
        foundationEndFile = stats.totalFiles;
        const foundationFileCount = foundationEndFile - foundationStartFile + 1;
        console.log(`\n🎉 ===========================================`);
        console.log(`🎉 foundation 目录扫描完成！`);
        console.log(`🎉 文件数: ${foundationFileCount} 个`);
        console.log(`🎉 起始文件编号: ${foundationStartFile}`);
        console.log(`🎉 结束文件编号: ${foundationEndFile}`);
        console.log(`🎉 最后处理的文件: ${stats.lastProcessedFile}`);
        console.log(`🎉 ===========================================\n`);
    }
    
    const scanTime = Date.now() - startTime;
    console.log(`✅ 扫描完成，耗时 ${(scanTime / 1000).toFixed(2)} 秒`);
    
    // 记录最后处理的文件和目录
    const lastProcessedInfo = {
        lastFile: stats.lastProcessedFile || '未知',
        lastDirectory: stats.lastProcessedDirectory || '未知',
        totalProcessed: stats.totalFiles,
        stoppedAt: new Date().toISOString()
    };
    
    console.log(`\n📌 扫描进度信息：`);
    console.log(`   - 最后处理的目录: ${lastProcessedInfo.lastDirectory}`);
    console.log(`   - 最后处理的文件: ${lastProcessedInfo.lastFile}`);
    console.log(`   - 总处理文件数: ${lastProcessedInfo.totalProcessed}`);
    console.log(`   - 停止时间: ${lastProcessedInfo.stoppedAt}`);
    
    // 分析并生成最佳实践
    console.log('📚 分析最佳实践...');
    
    // 注意：不在这里合并批次文件到内存，而是直接在保存时流式合并，避免内存溢出
    // 最佳实践分析需要基于已合并的数据，但数据量太大，这里先跳过，保存后再分析
    // 或者只基于内存中的部分数据进行分析
    
    // 先尝试从批次文件读取少量数据进行最佳实践分析（如果批次文件存在）
    const tempBatchDir = path.join(OUTPUT_DIR, 'temp_batches');
    let sampleDataForBestPractices = null;
    if (fs.existsSync(tempBatchDir)) {
        const batchFiles = fs.readdirSync(tempBatchDir)
            .filter(f => f.startsWith('batch-') && f.endsWith('.json'))
            .sort()
            .slice(0, 5); // 只读取前5个批次作为样本
        
        if (batchFiles.length > 0) {
            try {
                const sampleBatch = JSON.parse(fs.readFileSync(path.join(tempBatchDir, batchFiles[0]), 'utf-8'));
                sampleDataForBestPractices = {
                    functionCoveragePatterns: sampleBatch.functionCoveragePatterns || [],
                    testPatterns: sampleBatch.testPatterns || []
                };
            } catch (e) {
                // 忽略错误
            }
        }
    }
    
    // 基于内存中的数据和样本数据生成最佳实践
    const bestPractices = sampleDataForBestPractices ? 
        analyzeBestPractices({
            functionCoveragePatterns: [...knowledgeBase.functionCoveragePatterns, ...(sampleDataForBestPractices.functionCoveragePatterns || [])],
            testPatterns: [...knowledgeBase.testPatterns, ...(sampleDataForBestPractices.testPatterns || [])]
        }) : 
        analyzeBestPractices(knowledgeBase);
    knowledgeBase.bestPractices = bestPractices;
    
    // 更新统计信息
    knowledgeBase.metadata.stats = {
        ...stats,
        scanTimeMs: scanTime,
        lastProcessedInfo: lastProcessedInfo
    };
    
    // 保存知识库（使用分块保存避免内存溢出）
    console.log('💾 保存知识库...');
    
    // 如果存在批次文件，直接从批次文件合并保存，避免内存溢出
    const tempBatchDirForSave = path.join(OUTPUT_DIR, 'temp_batches');
    if (fs.existsSync(tempBatchDirForSave)) {
        console.log('📦 从批次文件合并保存知识库（流式处理，避免内存溢出）...');
        
        // 按类别合并批次文件
        const batchFiles = fs.readdirSync(tempBatchDirForSave)
            .filter(f => f.startsWith('batch-') && f.endsWith('.json'))
            .map(f => {
                const match = f.match(/batch-(\d+)\.json/);
                return match ? { file: f, number: parseInt(match[1]) } : null;
            })
            .filter(f => f !== null)
            .sort((a, b) => a.number - b.number);
        
        console.log(`   找到 ${batchFiles.length} 个批次文件，开始合并保存...`);
        
        // 按类别合并和保存
        const categories = [
            'classes', 'functions', 'headerDependencies', 'buildGnRelations', 
            'buildGnExternalDeps', 'testPatterns', 'testFileDependencies',
            'mockPatterns', 'functionCoveragePatterns', 'functionCallRelations',
            'testFunctionStrategies', 'branchCoveragePatterns', 'coverageQualityMetrics',
            'napiPatterns', 'ndkPatterns'
        ];
        
        let savedParts = 0;
        let totalSize = 0;
        
        for (const category of categories) {
            try {
                const partFile = path.join(OUTPUT_DIR, `oh-knowledge-base-${category}.json`);
                const writeStream = fs.createWriteStream(partFile, { encoding: 'utf-8' });
                
                // 写入数组开始
                writeStream.write('[\n');
                
                let firstItem = true;
                let itemCount = 0;
                
                // 遍历所有批次文件，提取该类别数据
                for (const batchFile of batchFiles) {
                    try {
                        const batchPath = path.join(tempBatchDirForSave, batchFile.file);
                        const batchData = JSON.parse(fs.readFileSync(batchPath, 'utf-8'));
                        const items = batchData[category] || [];
                        
                        for (const item of items) {
                            if (!firstItem) {
                                writeStream.write(',\n');
                            }
                            writeStream.write('  ' + JSON.stringify(item));
                            firstItem = false;
                            itemCount++;
                        }
                    } catch (error) {
                        console.warn(`   ⚠️ 处理批次 ${batchFile.number} 的 ${category} 失败: ${error.message}`);
                    }
                }
                
                // 同时写入内存中的剩余数据（如果有）
                const memoryItems = knowledgeBase[category] || [];
                for (const item of memoryItems) {
                    if (!firstItem) {
                        writeStream.write(',\n');
                    }
                    writeStream.write('  ' + JSON.stringify(item));
                    firstItem = false;
                    itemCount++;
                }
                
                // 写入数组结束
                writeStream.write('\n]');
                writeStream.end();
                
                await new Promise((resolve, reject) => {
                    writeStream.on('finish', () => {
                        const fileSize = fs.statSync(partFile).size;
                        totalSize += fileSize;
                        savedParts++;
                        console.log(`   ✓ ${category}: ${(fileSize / 1024 / 1024).toFixed(2)} MB (${itemCount} 条记录)`);
                        resolve();
                    });
                    writeStream.on('error', (err) => reject(err));
                });
            } catch (error) {
                console.error(`   ✗ ${category} 保存失败: ${error.message}`);
            }
        }
        
        // 保存metadata和bestPractices（这些通常很小）
        try {
            const metadataFile = path.join(OUTPUT_DIR, 'oh-knowledge-base-metadata.json');
            fs.writeFileSync(metadataFile, JSON.stringify(knowledgeBase.metadata, null, 2), 'utf-8');
            savedParts++;
            totalSize += fs.statSync(metadataFile).size;
            console.log(`   ✓ metadata: ${(fs.statSync(metadataFile).size / 1024 / 1024).toFixed(2)} MB`);
        } catch (error) {
            console.error(`   ✗ metadata 保存失败: ${error.message}`);
        }
        
        try {
            const bestPracticesFile = path.join(OUTPUT_DIR, 'oh-knowledge-base-bestPractices.json');
            fs.writeFileSync(bestPracticesFile, JSON.stringify(knowledgeBase.bestPractices, null, 2), 'utf-8');
            savedParts++;
            totalSize += fs.statSync(bestPracticesFile).size;
            console.log(`   ✓ bestPractices: ${(fs.statSync(bestPracticesFile).size / 1024 / 1024).toFixed(2)} MB`);
        } catch (error) {
            console.error(`   ✗ bestPractices 保存失败: ${error.message}`);
        }
        
        console.log(`✅ 从批次文件合并保存完成（${savedParts} 个部分）`);
        
        // 清理临时批次文件
        console.log('🧹 清理临时批次文件...');
        for (const batchFile of batchFiles) {
            try {
                fs.unlinkSync(path.join(tempBatchDirForSave, batchFile.file));
            } catch (e) {
                // 忽略删除错误
            }
        }
        try {
            fs.rmdirSync(tempBatchDirForSave);
        } catch (e) {
            // 忽略删除错误
        }
        console.log('✅ 临时文件清理完成');
    } else {
        // 没有批次文件，使用原来的方式（但数据量应该不大）
        console.log('📦 分块保存知识库（避免内存溢出）...');
        
        // 直接使用分块保存，避免一次性序列化大对象导致内存溢出
        // 每个部分单独保存，使用时按需加载
        const parts = {
            metadata: knowledgeBase.metadata,
            classes: knowledgeBase.classes,
            functions: knowledgeBase.functions,
            headerDependencies: knowledgeBase.headerDependencies,
            buildGnRelations: knowledgeBase.buildGnRelations,
            buildGnExternalDeps: knowledgeBase.buildGnExternalDeps,
            testPatterns: knowledgeBase.testPatterns,
            testFileDependencies: knowledgeBase.testFileDependencies,
            mockPatterns: knowledgeBase.mockPatterns,
            functionCoveragePatterns: knowledgeBase.functionCoveragePatterns,
            functionCallRelations: knowledgeBase.functionCallRelations,
            testFunctionStrategies: knowledgeBase.testFunctionStrategies,
            branchCoveragePatterns: knowledgeBase.branchCoveragePatterns,
            bestPractices: knowledgeBase.bestPractices,
            coverageQualityMetrics: knowledgeBase.coverageQualityMetrics,
            napiPatterns: knowledgeBase.napiPatterns,
            ndkPatterns: knowledgeBase.ndkPatterns
        };
        
        let savedParts = 0;
        let totalSize = 0;
        
        for (const [key, value] of Object.entries(parts)) {
            try {
                const partFile = path.join(OUTPUT_DIR, `oh-knowledge-base-${key}.json`);
                
                // 使用流式写入，避免一次性序列化
                const writeStream = fs.createWriteStream(partFile, { encoding: 'utf-8' });
                const jsonString = JSON.stringify(value, null, 2);
                
                // 分块写入，避免一次性写入大字符串
                const chunkSize = 1024 * 1024; // 1MB chunks
                for (let i = 0; i < jsonString.length; i += chunkSize) {
                    const chunk = jsonString.slice(i, i + chunkSize);
                    writeStream.write(chunk);
                }
                
                writeStream.end();
                
                await new Promise((resolve, reject) => {
                    writeStream.on('finish', () => {
                        const fileSize = fs.statSync(partFile).size;
                        totalSize += fileSize;
                        savedParts++;
                        console.log(`   ✓ ${key}: ${(fileSize / 1024 / 1024).toFixed(2)} MB`);
                        resolve();
                    });
                    writeStream.on('error', (err) => reject(err));
                });
            } catch (error) {
                console.error(`   ✗ ${key} 保存失败: ${error.message}`);
            }
        }
    }
    
    // 创建索引文件，方便快速加载
    const indexFile = path.join(OUTPUT_DIR, 'oh-knowledge-base-index.json');
    const index = {
        version: knowledgeBase.metadata.version,
        generatedAt: knowledgeBase.metadata.generatedAt,
        parts: Object.keys(parts).map(key => ({
            name: key,
            file: `oh-knowledge-base-${key}.json`
        })),
        stats: knowledgeBase.metadata.stats,
        totalSizeMB: (totalSize / 1024 / 1024).toFixed(2)
    };
    
    fs.writeFileSync(indexFile, JSON.stringify(index, null, 2), 'utf-8');
    console.log(`\n✅ 知识库已保存（${savedParts}/${Object.keys(parts).length} 个部分，总计 ${(totalSize / 1024 / 1024).toFixed(2)} MB）`);
    console.log(`   📋 索引文件: ${indexFile}`);
    console.log(`📊 统计信息:`);
    console.log(`   - 总文件数: ${stats.totalFiles}`);
    console.log(`   - 头文件: ${stats.headerFiles}`);
    console.log(`   - 源文件: ${stats.sourceFiles}`);
    console.log(`   - 测试文件: ${stats.testFiles}`);
    console.log(`   - BUILD.gn: ${stats.buildGnFiles}`);
    console.log(`   - 类: ${stats.classes}`);
    console.log(`   - 函数: ${stats.functions}`);
    console.log(`   - Mock: ${stats.mocks}`);
    console.log(`   - NAPI: ${stats.napiFunctions}`);
    console.log(`   - NDK: ${stats.ndkFunctions}`);
    console.log(`\n📚 知识库内容:`);
    console.log(`   - 类定义: ${knowledgeBase.classes.length} (统计总数: ${stats.classes})`);
    console.log(`   - 函数定义: ${knowledgeBase.functions.length} (统计总数: ${stats.functions})`);
    console.log(`   - 头文件依赖: ${knowledgeBase.headerDependencies.length}`);
    console.log(`   - BUILD.gn 关联: ${knowledgeBase.buildGnRelations.length}`);
    console.log(`   - external_deps 映射: ${knowledgeBase.buildGnExternalDeps.length}`);
    console.log(`   - 测试模式: ${knowledgeBase.testPatterns.length}`);
    console.log(`   - 测试文件依赖: ${knowledgeBase.testFileDependencies.length}`);
    console.log(`   - Mock 模式: ${knowledgeBase.mockPatterns.length} (统计总数: ${stats.mocks})`);
    console.log(`   - 函数覆盖模式: ${knowledgeBase.functionCoveragePatterns.length}`);
    console.log(`   - 函数调用关系: ${knowledgeBase.functionCallRelations.length}`);
    console.log(`   - 测试函数策略: ${knowledgeBase.testFunctionStrategies.length}`);
    console.log(`   - 分支覆盖模式: ${knowledgeBase.branchCoveragePatterns.length}`);
    console.log(`   - 覆盖质量指标: ${knowledgeBase.coverageQualityMetrics.length}`);
    console.log(`   - 最佳实践: ${knowledgeBase.bestPractices.length} 条`);
    console.log(`   - NAPI 模式: ${knowledgeBase.napiPatterns.length} (统计总数: ${stats.napiFunctions})`);
    console.log(`   - NDK 模式: ${knowledgeBase.ndkPatterns.length} (统计总数: ${stats.ndkFunctions})`);
    console.log(`\n✅ 知识库生成完成！所有数据已保存并通过分批机制合并`);
    console.log(`\n📋 扫描规则总结:`);
    console.log(`   ✓ 文件类型: .cpp, .h, .hpp, .c, .cc, .cxx, .hxx, BUILD.gn`);
    console.log(`   ✓ 类信息: 类定义、成员函数、成员变量、宏、访问修饰符、模板类`);
    console.log(`   ✓ 函数信息: 全局函数、成员函数、静态函数、内联函数、NAPI、NDK`);
    console.log(`   ✓ 测试模式: HWTEST/HWTEST_F/TEST/TEST_F、测试场景、断言类型`);
    console.log(`   ✓ Mock模式: MOCK_METHOD、EXPECT_CALL、ON_CALL、Mock组织方式`);
    console.log(`   ✓ BUILD.gn: targets、sources、external_deps、deps`);
    console.log(`   ✓ 头文件依赖: #include关系、系统/本地头文件`);
    console.log(`   ✓ 覆盖分析: 函数覆盖、分支覆盖、质量指标`);
    console.log(`   ✓ 最佳实践: 从实际代码中总结的测试模式`);
}

/**
 * 分析最佳实践（从知识库中总结规律）
 */
function analyzeBestPractices(knowledgeBase) {
    const practices = [];
    
    // 确保所有数组都存在，避免 undefined 错误
    const functionCoveragePatterns = knowledgeBase.functionCoveragePatterns || [];
    const testPatterns = knowledgeBase.testPatterns || [];
    const branchCoveragePatterns = knowledgeBase.branchCoveragePatterns || [];
    const coverageQualityMetrics = knowledgeBase.coverageQualityMetrics || [];
    
    // 1. 成员函数测试最佳实践
    const memberFunctionTests = functionCoveragePatterns.filter(p => 
        p.coverage && p.coverage.memberFunction && (p.coverage.memberFunction.hasPointerCall || p.coverage.memberFunction.hasObjectCall)
    );
    
    if (memberFunctionTests.length > 0) {
        const pointerUsage = {
            shared_ptr: memberFunctionTests.filter(t => t.coverage.memberFunction.hasSmartPointerCall).length,
            raw_pointer: memberFunctionTests.filter(t => t.coverage.memberFunction.hasPointerCall && !t.coverage.memberFunction.hasSmartPointerCall).length,
            object: memberFunctionTests.filter(t => t.coverage.memberFunction.hasObjectCall).length
        };
        
        practices.push({
            category: '成员函数测试',
            practice: '成员函数测试优先使用智能指针（shared_ptr）进行对象构造',
            evidence: {
                totalSamples: memberFunctionTests.length,
                usagePattern: pointerUsage,
                recommendation: pointerUsage.shared_ptr > pointerUsage.raw_pointer ? 
                    '使用 std::make_shared 构造对象' : '根据场景选择指针类型'
            },
            priority: 'high'
        });
    }
    
    // 2. 静态函数测试最佳实践
    const staticFunctionTests = functionCoveragePatterns.filter(p => 
        p.coverage && p.coverage.staticFunction && p.coverage.staticFunction.hasStaticCall
    );
    
    if (staticFunctionTests.length > 0) {
        practices.push({
            category: '静态函数测试',
            practice: '静态函数测试直接使用 ClassName::FunctionName() 调用',
            evidence: {
                totalSamples: staticFunctionTests.length,
                callPattern: 'ClassName::FunctionName()'
            },
            priority: 'high'
        });
    }
    
    // 3. SetUp/TearDown 最佳实践
    const setUpTests = testPatterns.filter(p => 
        p.setUpTearDown && p.setUpTearDown.hasSetUp
    );
    
    if (setUpTests.length > 0) {
        const setUpPatterns = setUpTests.map(t => t.setUpTearDown.setUpPatterns).flat();
        const commonInitPattern = {
            hasMockInit: setUpPatterns.filter(p => p.hasMockInit).length,
            hasInstanceInit: setUpPatterns.filter(p => p.hasInstanceInit).length,
            avgInitCount: setUpPatterns.reduce((sum, p) => sum + p.initCount, 0) / setUpPatterns.length
        };
        
        practices.push({
            category: 'SetUp/TearDown',
            practice: 'SetUp 中优先初始化 Mock 对象和被测实例，使用 std::make_shared',
            evidence: {
                totalSamples: setUpTests.length,
                commonPatterns: commonInitPattern,
                recommendation: 'SetUp 中初始化顺序：1) Mock 对象 2) 被测实例 3) 配置参数'
            },
            priority: 'high'
        });
    }
    
    // 4. 分支覆盖最佳实践
    const branchTests = branchCoveragePatterns;
    if (branchTests && branchTests.length > 0) {
        const highCoverageTests = branchTests.filter(t => t.coverageScore >= 10);
        
        practices.push({
            category: '分支覆盖',
            practice: '测试应覆盖主要分支：if/else、switch/case、异常处理、边界值检查',
            evidence: {
                totalSamples: branchTests.length,
                highCoverageCount: highCoverageTests.length,
                avgCoverageScore: branchTests.reduce((sum, t) => sum + t.coverageScore, 0) / branchTests.length,
                recommendedBranches: ['if/else', 'switch/case', '异常处理', '空值检查', '边界值检查']
            },
            priority: 'critical'
        });
    }
    
    // 5. 高质量测试最佳实践
    const highQualityTests = coverageQualityMetrics.filter(m => m && m.isHighQuality);
    
    if (highQualityTests.length > 0) {
        const avgQuality = highQualityTests.reduce((sum, t) => sum + t.qualityScore, 0) / highQualityTests.length;
        const avgAssertions = highQualityTests.reduce((sum, t) => sum + t.quality.assertions.count, 0) / highQualityTests.length;
        
        practices.push({
            category: '测试质量',
            practice: '高质量测试特征：多个断言、多种场景、使用智能指针、包含日志',
            evidence: {
                totalSamples: highQualityTests.length,
                avgQualityScore: avgQuality,
                avgAssertions: avgAssertions,
                characteristics: {
                    multipleAssertions: highQualityTests.filter(t => t.quality.assertions.hasMultipleAssertions).length,
                    multipleScenarios: highQualityTests.filter(t => t.quality.scenarios.scenarioCount > 1).length,
                    smartPointerUsage: highQualityTests.filter(t => t.quality.objectUsage.hasSmartPointer).length,
                    hasLogging: highQualityTests.filter(t => t.quality.codeQuality.hasLogging).length
                }
            },
            priority: 'critical'
        });
    }
    
    // 6. Mock 使用时机最佳实践
    const mockTests = knowledgeBase.mockPatterns.filter(p => p.type === 'mock_usage_in_test');
    
    if (mockTests.length > 0) {
        const mockScenarios = {
            errorCase: mockTests.filter(t => t.testFunctions && t.testFunctions.some(f => /error|fail|exception/i.test(f.name))).length,
            boundaryCase: mockTests.filter(t => t.testFunctions && t.testFunctions.some(f => /boundary|limit/i.test(f.name))).length,
            normalCase: mockTests.filter(t => t.testFunctions && t.testFunctions.some(f => !/error|fail|boundary/i.test(f.name))).length
        };
        
        practices.push({
            category: 'Mock 使用时机',
            practice: 'Mock 主要用于：外部依赖、系统服务、复杂对象、错误场景模拟',
            evidence: {
                totalSamples: mockTests.length,
                scenarioDistribution: mockScenarios,
                recommendation: '当需要隔离外部依赖或模拟特定场景时使用 Mock'
            },
            priority: 'high'
        });
    }
    
    // 7. 同文件/同模块函数调用最佳实践
    const sameFileModuleTests = knowledgeBase.testFunctionStrategies.filter(s => 
        s.strategies && s.strategies.sameFileModuleStrategy && 
        (s.strategies.sameFileModuleStrategy.hasSameFileCall || s.strategies.sameFileModuleStrategy.hasSameModuleCall)
    );
    
    if (sameFileModuleTests.length > 0) {
        practices.push({
            category: '函数调用链',
            practice: '测试被覆盖函数时，同时测试其调用的同文件或同模块辅助函数',
            evidence: {
                totalSamples: sameFileModuleTests.length,
                sameFileCallCount: sameFileModuleTests.filter(s => s.strategies.sameFileModuleStrategy.hasSameFileCall).length,
                sameModuleCallCount: sameFileModuleTests.filter(s => s.strategies.sameFileModuleStrategy.hasSameModuleCall).length
            },
            priority: 'medium'
        });
    }
    
    return practices;
}

// 运行主函数
if (require.main === module) {
    main().catch(error => {
        console.error('❌ 主函数执行失败:', error);
        process.exit(1);
    });
}

module.exports = { main };

